value.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  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 <vector>
  51. #include <tuple>
  52. #include <initializer_list>
  53. #include <functional>
  54. #include "log.hpp"
  55. /**
  56. * The namespace containing all filval classes and functions.
  57. */
  58. namespace fv{
  59. /* bool in_register_function = false; */
  60. template<typename> class Function; // undefined
  61. /**
  62. * Parent class to all Function classes. Holds a class-level collection of all
  63. * created function objects.
  64. */
  65. class GenFunction {
  66. private:
  67. std::string name;
  68. std::string impl;
  69. protected:
  70. inline static bool in_register_function=false;
  71. public:
  72. /**
  73. * Static mapping of functions from their name to the object wrapper of
  74. * the function.
  75. */
  76. inline static std::map<const std::string, GenFunction*> function_registry;
  77. GenFunction(const std::string& name, const std::string& impl)
  78. :impl(impl),
  79. name(name){
  80. }
  81. virtual ~GenFunction() { };
  82. std::string& get_name(){
  83. return name;
  84. }
  85. /**
  86. * Attempt to invoke clang-format for the purpose of printing out
  87. * nicely formatted functions to the log file. If clang-format is not
  88. * present, this function just passes through the code unmodified.
  89. */
  90. static std::string format_code(const std::string& code){
  91. std::stringstream code_out("");
  92. std::string command("echo \""+code+"\" | clang-format");
  93. char buffer[255];
  94. FILE *stream = popen(command.c_str(), "r");
  95. while (fgets(buffer, 255, stream) != NULL)
  96. code_out << buffer;
  97. if (pclose(stream) == 0)
  98. return code_out.str();
  99. else
  100. return code;
  101. }
  102. static std::string summary(){
  103. std::stringstream ss;
  104. ss << "The following functions have been registered" << std::endl;
  105. for(auto p : function_registry){
  106. if (p.second == nullptr) continue;
  107. ss << "-->" << p.second->name << std::endl;
  108. ss << format_code(p.second->impl);
  109. }
  110. return ss.str();
  111. }
  112. template <typename T>
  113. static Function<T>& register_function(const std::string& name, std::function<T> f, const std::string& impl){
  114. in_register_function = true;
  115. Function<T>* func;
  116. if (GenFunction::function_registry[name] != nullptr){
  117. func = dynamic_cast<Function<T>*>(GenFunction::function_registry[name]);
  118. if (func == nullptr){
  119. ERROR("Trying to register function which has already been registered with a different type");
  120. }
  121. } else {
  122. func = new Function<T>(name, impl, f);
  123. GenFunction::function_registry[name] = func;
  124. }
  125. in_register_function = false;
  126. return *func;
  127. }
  128. };
  129. /**
  130. * In order to enable proper provenance tracking, and at the same time keep
  131. * the ability to embed functions into values, the Function class should be
  132. * used. It is simply a wrapper around a std::function that also has a name.
  133. * This name is used when generating the name of values that use the function.
  134. * A function name is automatically prepended with "func::" to explicitly state
  135. * that the value is the result of a computation encoded within the function
  136. * object, and not from some other Value object. Unfortunately, it is up to the
  137. * user to find where that function is defined in the source code to inspect
  138. * what it is doing. But hopefully this isn't too onerous by just using grep.
  139. */
  140. template <typename R, typename... ArgTypes>
  141. class Function<R(ArgTypes...)> : public GenFunction {
  142. private:
  143. std::function<R(ArgTypes...)> f;
  144. public:
  145. Function(const std::string& name, const std::string& impl, std::function<R(ArgTypes...)> f)
  146. :GenFunction(name, impl), f(f){
  147. if (!in_register_function) {
  148. WARNING("Don't instantiate Function objects directly! Use GenFunction::register_function instead.");
  149. }
  150. }
  151. Function(const std::string& name, std::function<R(ArgTypes...)> f)
  152. :Function(name, "N/A", f){ }
  153. ~Function() { }
  154. R operator()(ArgTypes ...args){
  155. return f(args...);
  156. }
  157. };
  158. #define FUNC(f) f, #f
  159. /**
  160. * A type-agnostic value.
  161. * It is necessary to create a type-agnostic parent class to Value so that
  162. * it is possible to handle collections of them. GenValue also provides the
  163. * rest of the type-independent interface to Value.
  164. */
  165. class GenValue;
  166. typedef std::map<std::string, GenValue*> ValueSet;
  167. class GenValue{
  168. private:
  169. /**
  170. * The name of the value.
  171. * This is used to allow for dynamic lookup of
  172. * values based on their name via GenValue::get_value.
  173. */
  174. std::string name;
  175. protected:
  176. /**
  177. * Mark the internal value as invalid. This is needed for DerivedValue
  178. * to force a recalculation of the internal value when a new
  179. * observation is loaded into memory. It is called automatically for
  180. * all GenValue objects when reset is called.
  181. */
  182. virtual void _reset() = 0;
  183. /**
  184. * A static mapping containing all created Value objects.
  185. * Every value object must have a unique name, and this name is used as
  186. * a key in values to that object. This is used to enable more dynamic
  187. * creation of objects as well as avoiding the uneccesary passing of
  188. * pointers.
  189. */
  190. inline static std::map<const std::string, GenValue*> values;
  191. /**
  192. * Composite value names are typically nested. This makes complex
  193. * values have rather unwieldy names. Therefore, one can declare
  194. * aliases which allow for more human-usable names to be used. When a
  195. * value is requested by name, an alias with that value takes precidence
  196. * over a name with that value.
  197. */
  198. inline static std::map<const std::string, GenValue*> aliases;
  199. public:
  200. GenValue(const std::string& name, const std::string& alias)
  201. :name(name){
  202. values[name] = this;
  203. if (alias != "")
  204. GenValue::alias(alias, this);
  205. }
  206. const std::string& get_name(){
  207. return name;
  208. }
  209. static void reset(){
  210. for (auto val : values){
  211. val.second->_reset();
  212. }
  213. }
  214. static GenValue* get_value(const std::string& name){
  215. if (aliases[name] != nullptr)
  216. return aliases[name];
  217. else if (values[name] != nullptr)
  218. return values[name];
  219. else{
  220. ERROR("Could not find alias or value \"" << name << "\". I'll tell you the ones I know about." << std::endl
  221. << summary());
  222. CRITICAL("Aborting... :(", -1);
  223. }
  224. }
  225. static void alias(const std::string& name, GenValue* value){
  226. if (aliases[name] != nullptr){
  227. WARNING("WARNING: alias \"" << name << "\" overrides previous entry.");
  228. }
  229. aliases[name] = value;
  230. }
  231. static GenValue* alias(const std::string& name){
  232. if (values[name] != nullptr){
  233. WARNING("Alias \"" << name << "\" does not exist.");
  234. }
  235. return aliases[name];
  236. }
  237. static std::string summary(){
  238. std::stringstream ss;
  239. ss << "The following values have been created: " << std::endl;
  240. for (auto value : values){
  241. if (value.second == nullptr) continue;
  242. ss << "\t\"" << value.first << "\" at address " << value.second << std::endl;
  243. }
  244. ss << "And these aliases:" << std::endl;
  245. for (auto alias : aliases){
  246. std::string orig("VOID");
  247. if (alias.second == nullptr) continue;
  248. for (auto value : values){
  249. if (alias.second == value.second){
  250. orig = value.second->get_name();
  251. break;
  252. }
  253. }
  254. ss << "\t\"" << alias.first << "\" referring to \"" << orig << "\"" << std::endl;
  255. }
  256. return ss.str();
  257. }
  258. friend std::ostream& operator<<(std::ostream& os, const GenValue& gv);
  259. };
  260. std::ostream& operator<<(std::ostream& os, GenValue& gv){
  261. os << gv.get_name();
  262. return os;
  263. }
  264. /**
  265. * A generic value.
  266. * In order to facilitate run-time creation of analysis routines, it is
  267. * necessary to have some ability to get and store *values*. Values can either
  268. * be directly taken from some original data source (i.e. ObservedValue), or
  269. * they can be a function of some other set of values (i.e. DerivedValue). They
  270. * template class T of Value<T> is the type of thing that is returned upon
  271. * calling get_value().
  272. */
  273. template <typename T>
  274. class Value : public GenValue{
  275. public:
  276. Value(const std::string& name, const std::string& alias="")
  277. :GenValue(name, alias){ }
  278. /** Calculate, if necessary, and return the value held by this object.
  279. */
  280. virtual T& get_value() = 0;
  281. };
  282. /**
  283. * A generic, observed, value.
  284. * An ObservedValue is the interface to your dataset. Upon creation, an
  285. * ObservedValue is given a pointer to an object of type T. When an observation
  286. * is loaded into memory, the value at the location referenced by that pointer
  287. * must be updated with the associated data from that observation. This is the
  288. * responsibility of whatever DataSet implementation is being used. This object
  289. * then will read that data and return it when requested.
  290. */
  291. template <typename T>
  292. class ObservedValue : public Value<T>{
  293. private:
  294. T *val_ref;
  295. void _reset(){ }
  296. public:
  297. ObservedValue(const std::string& name, T* val_ref, const std::string& alias="")
  298. :Value<T>(name, alias),
  299. val_ref(val_ref){ }
  300. T& get_value(){
  301. return *val_ref;
  302. }
  303. };
  304. /**
  305. * A generic, derived, value.
  306. * A DerivedValue is generally defined as some function of other Value objects.
  307. * For example, a Pair is a function of two other Value objects that makes a
  308. * pair of them. Note that these other Value objects are free to be either
  309. * ObservedValues or other DerivedValues.
  310. *
  311. * It is desireable from a performance standpoint that each DerivedValue be
  312. * calculated no more than once per observation. Therefore, when a get_value is
  313. * called on a DerivedValue, it first checks whether the value that it holds is
  314. * **valid**, meaning it has already been calculated for this observation. If
  315. * so, it simply returns the value. If not, the update_value function is called
  316. * to calculate the value. and then the newly calculated value is marked as
  317. * valid and returned.
  318. */
  319. template <typename T>
  320. class DerivedValue : public Value<T>{
  321. private:
  322. void _reset(){
  323. value_valid = false;
  324. }
  325. protected:
  326. T value;
  327. bool value_valid;
  328. /**
  329. * Updates the internal value.
  330. * This function should be overridden by any child class to do the
  331. * actual work of updating value based on whatever rules the class
  332. * chooses. Normally, this consists of geting the values from some
  333. * associated Value objects, doing some calculation on them, and
  334. * storing the result in value.
  335. */
  336. virtual void update_value() = 0;
  337. public:
  338. DerivedValue(const std::string& name, const std::string& alias="")
  339. :Value<T>(name, alias),
  340. value_valid(false) { }
  341. T& get_value(){
  342. if (!value_valid){
  343. update_value();
  344. value_valid = true;
  345. }
  346. return value;
  347. }
  348. };
  349. /**
  350. * A std::vector wrapper around a C-style array.
  351. * In order to make some of the higher-level Value types easier to work with,
  352. * it is a good idea to wrap all arrays in the original data source with
  353. * std::vector objects. To do this, it is necessary to supply both a Value
  354. * object containing the array itself as well as another Value object
  355. * containing the size of that array. Currently, update_value will simply copy
  356. * the contents of the array into the interally held vector.
  357. */
  358. template <typename T>
  359. class WrapperVector : public DerivedValue<std::vector<T> >{
  360. private:
  361. Value<int>* size;
  362. Value<T*>* data;
  363. void update_value(){
  364. int n = size->get_value();
  365. T* data_ref = data->get_value();
  366. this->value.assign(data_ref, data_ref+n);
  367. }
  368. public:
  369. WrapperVector(Value<int>* size, Value<T*>* data, const std::string& alias="")
  370. :DerivedValue<std::vector<T> >("vectorOf("+size->get_name()+","+data->get_name()+")", alias),
  371. size(size), data(data){ }
  372. WrapperVector(const std::string &label_size, const std::string &label_data, const std::string& alias="")
  373. :WrapperVector(dynamic_cast<Value<int>*>(GenValue::get_value(label_size)),
  374. dynamic_cast<Value<T*>*>(GenValue::get_value(label_data)), alias) { }
  375. };
  376. /**
  377. * Creates a std::pair type from a two other Value objects.
  378. */
  379. template <typename T1, typename T2>
  380. class Pair : public DerivedValue<std::pair<T1, T2> >{
  381. protected:
  382. std::pair<Value<T1>*, Value<T2>* > value_pair;
  383. void update_value(){
  384. this->value.first = value_pair.first->get_value();
  385. this->value.second = value_pair.second->get_value();
  386. }
  387. public:
  388. Pair(Value<T1> *value1, Value<T2> *value2, const std::string alias="")
  389. :DerivedValue<std::pair<T1, T2> >("pair("+value1->get_name()+","+value2->get_name()+")", alias),
  390. value_pair(value1, value2){ }
  391. Pair(const std::string& label1, const std::string& label2, const std::string alias="")
  392. :Pair(dynamic_cast<Value<T1>*>(GenValue::get_value(label1)),
  393. dynamic_cast<Value<T1>*>(GenValue::get_value(label2)),
  394. alias){ }
  395. };
  396. /**
  397. * Takes a set of four Value<std::vector<T> > objects and a function of four Ts
  398. * and returns a std::vector<R>. This is used in, for instance, calculating the
  399. * energy of a set of particles when one has separate arrays containing pt,
  400. * eta, phi, and mass. These arrays are first wrapped up in VectorWrappers and
  401. * then passes along with a function to calculate the energy into a ZipMapFour.
  402. * The result of this calculation is a new vector containing the energy for
  403. * each particle. Note that if the input vectors are not all the same size,
  404. * calculations are only performed up to the size of the shortest.
  405. * \see MiniTreeDataSet
  406. * \todo find way to implement for arbitrary number(and possibly type) of
  407. * vector inputs.
  408. */
  409. template <typename R, typename T>
  410. class ZipMapFour : public DerivedValue<std::vector<R> >{
  411. private:
  412. Function<R(T, T, T, T)>& f;
  413. Value<std::vector<T> >* v1;
  414. Value<std::vector<T> >* v2;
  415. Value<std::vector<T> >* v3;
  416. Value<std::vector<T> >* v4;
  417. void update_value(){
  418. std::vector<T> v1_val = v1->get_value();
  419. std::vector<T> v2_val = v2->get_value();
  420. std::vector<T> v3_val = v3->get_value();
  421. std::vector<T> v4_val = v4->get_value();
  422. int n;
  423. std::tie(n, std::ignore) = std::minmax({v1_val.size(), v2_val.size(), v3_val.size(), v4_val.size()});
  424. this->value.resize(n);
  425. for (int i=0; i<n; i++){
  426. this->value[i] = f(v1_val[i], v2_val[i], v3_val[i], v4_val[i]);
  427. }
  428. }
  429. public:
  430. ZipMapFour(Function<R(T, T, T, T)>& f,
  431. Value<std::vector<T> >* v1, Value<std::vector<T> >* v2,
  432. Value<std::vector<T> >* v3, Value<std::vector<T> >* v4, const std::string alias="")
  433. :DerivedValue<std::vector<R> >("zipmap("+f.get_name()+":"+v1->get_name()+","+v2->get_name()+","+
  434. v3->get_name()+","+v4->get_name()+")", alias),
  435. f(f), v1(v1), v2(v2), v3(v3), v4(v4) { }
  436. ZipMapFour(Function<R(T, T, T, T)>& f,
  437. const std::string& label1, const std::string& label2,
  438. const std::string& label3, const std::string& label4, const std::string alias="")
  439. :ZipMapFour(f,
  440. dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(label1)),
  441. dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(label2)),
  442. dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(label3)),
  443. dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(label4)),
  444. alias){ }
  445. };
  446. /**
  447. * Reduce a Value of type vector<T> to just a T.
  448. * This is useful functionality to model, for instance, calculating the maximum
  449. * element of a vector, or a the mean. See child classes for specific
  450. * implementations.
  451. */
  452. template <typename T>
  453. class Reduce : public DerivedValue<T>{
  454. private:
  455. Function<T(std::vector<T>)>& reduce;
  456. Value<std::vector<T> >* v;
  457. void update_value(){
  458. this->value = reduce(v->get_value());
  459. }
  460. public:
  461. Reduce(Function<T(std::vector<T>)>& reduce, Value<std::vector<T> >* v, const std::string alias="")
  462. :DerivedValue<T>("reduceWith("+reduce.get_name()+":"+v->get_name()+")", alias),
  463. reduce(reduce), v(v) { }
  464. Reduce(Function<T(std::vector<T>)>& reduce, const std::string& v_name, const std::string alias="")
  465. :Reduce(reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name)), alias) { }
  466. };
  467. /**
  468. * Find and return the maximum value of a vector.
  469. */
  470. template <typename T>
  471. class Max : public Reduce<T>{
  472. public:
  473. Max(const std::string& v_name, const std::string alias="")
  474. :Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("max",
  475. FUNC(([](std::vector<T> vec){
  476. return *std::max_element(vec.begin(), vec.end());}))),
  477. v_name, alias) { }
  478. };
  479. /**
  480. * Find and return the minimum value of a vector.
  481. */
  482. template <typename T>
  483. class Min : public Reduce<T>{
  484. public:
  485. Min(const std::string& v_name, const std::string alias="")
  486. :Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("min",
  487. FUNC(([](std::vector<T> vec){
  488. return *std::min_element(vec.begin(), vec.end());}))),
  489. v_name, alias) { }
  490. };
  491. /**
  492. * Calculate the mean value of a vector.
  493. */
  494. template <typename T>
  495. class Mean : public Reduce<T>{
  496. public:
  497. Mean(const std::string& v_name, const std::string alias="")
  498. :Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("mean",
  499. FUNC(([](std::vector<T> vec){
  500. int n = 0; T sum = 0;
  501. for (T e : vec){ n++; sum += e; }
  502. return n>0 ? sum / n : 0; }))),
  503. v_name, alias) { }
  504. };
  505. /**
  506. * Calculate the range of the values in a vector
  507. */
  508. template <typename T>
  509. class Range : public Reduce<T>{
  510. public:
  511. Range(const std::string& v_name, const std::string alias="")
  512. :Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("range",
  513. FUNC(([](std::vector<T> vec){
  514. auto minmax = std::minmax_element(vec.begin(), vec.end());
  515. return (*minmax.second) - (*minmax.first); }))),
  516. v_name, alias) { }
  517. };
  518. /**
  519. * Extract the element at a specific index from a vector.
  520. */
  521. template <typename T>
  522. class ElementOf : public Reduce<T>{
  523. public:
  524. ElementOf(Value<int>* index, const std::string& v_name, const std::string alias="")
  525. :Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("elementOf",
  526. FUNC(([index](std::vector<T> vec){return vec[index->get_value()];}))),
  527. v_name, alias) { }
  528. ElementOf(const std::string& name, int index, const std::string& v_name, const std::string alias="")
  529. :Reduce<T>(name, [index](std::vector<T> vec){return vec[index];}, v_name, alias) { }
  530. };
  531. /**
  532. * Similar to Reduce, but returns a pair of a T and an int.
  533. * This is useful if you need to know where in the vector exists the element
  534. * being returned.
  535. */
  536. template <typename T>
  537. class ReduceIndex : public DerivedValue<std::pair<T, int> >{
  538. private:
  539. Function<std::pair<T,int>(std::vector<T>)>& reduce;
  540. Value<std::vector<T> >* v;
  541. void update_value(){
  542. this->value = reduce(v->get_value());
  543. }
  544. public:
  545. ReduceIndex(Function<std::pair<T,int>(std::vector<T>)>& reduce, Value<std::vector<T> >* v, const std::string alias="")
  546. :DerivedValue<T>("reduceIndexWith("+reduce.get_name()+":"+v->get_name()+")", alias),
  547. reduce(reduce), v(v) { }
  548. ReduceIndex(Function<std::pair<T,int>(std::vector<T>)>& reduce, const std::string& v_name, const std::string alias="")
  549. :ReduceIndex(reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name)), alias) { }
  550. };
  551. /**
  552. * Find and return the maximum value of a vector and its index.
  553. */
  554. template <typename T>
  555. class MaxIndex : public ReduceIndex<T>{
  556. public:
  557. MaxIndex(const std::string& v_name, const std::string alias="")
  558. :ReduceIndex<T>(GenFunction::register_function<T(std::vector<T>)>("maxIndex",
  559. FUNC(([](std::vector<T> vec){
  560. auto elptr = std::max_element(vec.begin(), vec.end());
  561. return std::pair<T,int>(*elptr, int(elptr-vec.begin())); }
  562. ))), v_name, alias) { }
  563. };
  564. /**
  565. * Find and return the minimum value of a vector and its index.
  566. */
  567. template <typename T>
  568. class MinIndex : public ReduceIndex<T>{
  569. public:
  570. MinIndex(const std::string& v_name, const std::string alias="")
  571. :ReduceIndex<T>(GenFunction::register_function<T(std::vector<T>)>("minIndex",
  572. FUNC(([](std::vector<T> vec){
  573. auto elptr = std::min_element(vec.begin(), vec.end());
  574. return std::pair<T,int>(*elptr, int(elptr-vec.begin())); }
  575. ))), v_name, alias) { }
  576. };
  577. /**
  578. * A generic value owning only a function object.
  579. * All necessary values upon which this value depends must be bound to the
  580. * function object.
  581. */
  582. template <typename T>
  583. class BoundValue : public DerivedValue<T>{
  584. protected:
  585. Function<T()>& f;
  586. void update_value(){
  587. this->value = f();
  588. }
  589. public:
  590. BoundValue(Function<T()>& f, const std::string alias="")
  591. :DerivedValue<T>(f.get_name()+"(<bound>)", alias),
  592. f(f) { }
  593. };
  594. /**
  595. * A Value of a pointer. The pointer is constant, however the data the pointer
  596. * points to is variable.
  597. */
  598. template <typename T>
  599. class PointerValue : public DerivedValue<T*>{
  600. protected:
  601. void update_value(){ }
  602. public:
  603. PointerValue(const std::string& name, T* ptr, const std::string alias="")
  604. :DerivedValue<T*>(name, alias){
  605. this->value = ptr;
  606. }
  607. };
  608. /**
  609. * A Value which always returns the same value, supplied in the constructor.
  610. */
  611. template <typename T>
  612. class ConstantValue : public DerivedValue<T>{
  613. protected:
  614. T const_value;
  615. void update_value(){
  616. this->value = const_value;
  617. }
  618. public:
  619. ConstantValue(const std::string& name, T const_value, const std::string alias="")
  620. :DerivedValue<T>("const::"+name, alias),
  621. const_value(const_value) { }
  622. };
  623. }
  624. #endif // value_hpp