# TTTT Analysis: /home/caleb/Sources/TTTT/filval/value.hpp Source File

value.hpp
Go to the documentation of this file.
#ifndef value_hpp
#define value_hpp
#include <iomanip>
#include <iostream>
#include <sstream>
#include <utility>
#include <algorithm>
#include <map>
#include <limits>
#include <vector>
#include <tuple>
#include <initializer_list>
#include <functional>
#include "log.hpp"
namespace fv{
template <typename F, typename TUPLE, bool Done, int Total, int... N>
struct call_impl
{
static auto call(F& f, TUPLE && t)
{
return call_impl<F, TUPLE, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(f, std::forward<TUPLE>(t));
}
};
template <typename F, typename TUPLE, int Total, int... N>
struct call_impl<F, TUPLE, true, Total, N...>
{
static auto call(F& f, TUPLE && t)
{
return f(std::get<N>(std::forward<TUPLE>(t))...);
}
};
template <typename F, typename TUPLE>
auto call(F& f, TUPLE && t)
{
typedef typename std::decay<TUPLE>::type ttype;
return call_impl<F, TUPLE, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(f, std::forward<TUPLE>(t));
}
template<typename> class Function; // undefined
class GenFunction {
private:
std::string name;
std::string impl;
protected:
inline static bool in_register_function=false;
public:
inline static std::map<const std::string, GenFunction*> function_registry;
GenFunction(const std::string& name, const std::string& impl)
:name(name),
impl(impl){ }
virtual ~GenFunction() { };
std::string& get_name(){
return name;
}
static std::string format_code(const std::string& code){
std::stringstream code_out("");
std::string command("echo \""+code+"\" | clang-format");
char buffer[255];
FILE *stream = popen(command.c_str(), "r");
while (fgets(buffer, 255, stream) != NULL)
code_out << buffer;
if (pclose(stream) == 0)
return code_out.str();
else
return code;
}
static std::string summary(){
std::stringstream ss;
ss << "The following functions have been registered" << std::endl;
for(auto p : function_registry){
if (p.second == nullptr) continue;
ss << "-->" << p.second->name << "@" << p.second << std::endl;
ss << format_code(p.second->impl);
}
return ss.str();
}
template <typename T>
static Function<T>& register_function(const std::string& name, std::function<T> f, const std::string& impl){
in_register_function = true;
Function<T>* func;
if (GenFunction::function_registry[name] != nullptr){
func = dynamic_cast<Function<T>*>(GenFunction::function_registry[name]);
if (func == nullptr){
ERROR("Trying to register function which has already been registered with a different type");
}
} else {
func = new Function<T>(name, impl, f);
GenFunction::function_registry[name] = func;
}
in_register_function = false;
return *func;
}
};
template <typename R, typename... ArgTypes>
class Function<R(ArgTypes...)> : public GenFunction {
private:
std::function<R(ArgTypes...)> f;
public:
Function(const std::string& name, const std::string& impl, std::function<R(ArgTypes...)> f)
:GenFunction(name, impl), f(f){
if (!in_register_function) {
WARNING("Don't instantiate Function objects directly! Use GenFunction::register_function instead.");
}
}
Function(const std::string& name, std::function<R(ArgTypes...)> f)
:Function(name, "N/A", f){ }
~Function() { }
R operator()(ArgTypes ...args){
return f(args...);
}
};
#define FUNC(f) f, #f
class GenValue;
typedef std::map<std::string, GenValue*> ValueSet;
class GenValue{
private:
std::string name;
protected:
virtual void _reset() = 0;
inline static std::map<const std::string, GenValue*> values;
inline static std::map<const std::string, GenValue*> aliases;
public:
GenValue(const std::string& name, const std::string& alias)
:name(name){
values[name] = this;
if (alias != "")
GenValue::alias(alias, this);
}
const std::string& get_name(){
return name;
}
void set_name(const std::string& new_name){
values[name] = nullptr;
name = new_name;
values[name] = this;
}
static void reset(){
for (auto val : values){
if (val.second != nullptr){
val.second->_reset();
}
}
}
static GenValue* get_value(const std::string& name){
if (aliases[name] != nullptr)
return aliases[name];
else if (values[name] != nullptr)
return values[name];
else{
ERROR("Could not find alias or value \"" << name << "\". I'll tell you the ones I know about." << std::endl
<< summary());
CRITICAL("Aborting... :(",-1);
}
}
static void alias(const std::string& name, GenValue* value){
if (aliases[name] != nullptr){
WARNING("WARNING: alias \"" << name << "\" overrides previous entry.");
}
aliases[name] = value;
}
static GenValue* alias(const std::string& name){
if (values[name] != nullptr){
WARNING("Alias \"" << name << "\" does not exist.");
}
return aliases[name];
}
static std::string summary(){
std::stringstream ss;
ss << "The following values have been created: " << std::endl;
for (auto value : values){
if (value.second == nullptr) continue;
ss << "\t\"" << value.first << "\" at address " << value.second << std::endl;
}
ss << "And these aliases:" << std::endl;
for (auto alias : aliases){
std::string orig("VOID");
if (alias.second == nullptr) continue;
for (auto value : values){
if (alias.second == value.second){
orig = value.second->get_name();
break;
}
}
ss << "\t\"" << alias.first << "\" referring to \"" << orig << "\"" << std::endl;
}
return ss.str();
}
friend std::ostream& operator<<(std::ostream& os, const GenValue& gv);
};
std::ostream& operator<<(std::ostream& os, GenValue& gv){
os << gv.get_name();
return os;
}
template <typename T>
class Value : public GenValue{
public:
Value(const std::string& name, const std::string& alias="")
:GenValue(name, alias){ }
virtual T& get_value() = 0;
};
template <typename T>
class ObservedValue : public Value<T>{
private:
T *val_ref;
void _reset(){ }
public:
ObservedValue(const std::string& name, T* val_ref, const std::string& alias="")
:Value<T>(name, alias),
val_ref(val_ref){ }
T& get_value(){
return *val_ref;
}
};
template <typename T>
class DerivedValue : public Value<T>{
private:
void _reset(){
value_valid = false;
}
protected:
T value;
bool value_valid;
virtual void update_value() = 0;
public:
DerivedValue(const std::string& name, const std::string& alias="")
:Value<T>(name, alias),
value_valid(false) { }
T& get_value(){
if (!value_valid){
update_value();
value_valid = true;
}
return value;
}
};
template <typename T>
class WrapperVector : public DerivedValue<std::vector<T> >{
private:
Value<int>* size;
Value<T*>* data;
void update_value(){
int n = size->get_value();
T* data_ref = data->get_value();
this->value.assign(data_ref, data_ref+n);
}
public:
WrapperVector(Value<int>* size, Value<T*>* data, const std::string& alias="")
:DerivedValue<std::vector<T> >("vectorOf("+size->get_name()+","+data->get_name()+")", alias),
size(size), data(data){ }
};
template <typename T1, typename T2>
class Pair : public DerivedValue<std::pair<T1, T2> >{
protected:
std::pair<Value<T1>*, Value<T2>* > value_pair;
void update_value(){
this->value.first = value_pair.first->get_value();
this->value.second = value_pair.second->get_value();
}
public:
Pair(Value<T1> *value1, Value<T2> *value2, const std::string alias="")
:DerivedValue<std::pair<T1, T2> >("pair("+value1->get_name()+","+value2->get_name()+")", alias),
value_pair(value1, value2){ }
};
template<typename... T> class _Zip;
template<>
class _Zip<> {
protected:
int _get_size(){
return std::numeric_limits<int>::max();
}
std::tuple<> _get_at(int idx){
return std::make_tuple();
}
std::string _get_name(){
return "";
}
public:
_Zip() { }
};
template<typename Head, typename... Tail>
class _Zip<Head, Tail...> : private _Zip<Tail...> {
protected:
Value<std::vector<Head>>* head;
int _get_size(){
int this_size = head->get_value().size();
int rest_size = _Zip<Tail...>::_get_size();
return std::min(this_size, rest_size);
}
typename std::tuple<Head,Tail...> _get_at(int idx){
auto tail_tuple = _Zip<Tail...>::_get_at(idx);
return std::tuple_cat(std::make_tuple(head->get_value()[idx]),tail_tuple);
}
std::string _get_name(){
return head->get_name()+","+_Zip<Tail...>::_get_name();
}
public:
_Zip() { }
_Zip(Value<std::vector<Head>>* head, Value<std::vector<Tail>>*... tail)
: _Zip<Tail...>(tail...),
head(head) { }
};
template <typename... ArgTypes>
class Zip : public DerivedValue<std::vector<std::tuple<ArgTypes...>>>,
private _Zip<ArgTypes...>{
protected:
void update_value(){
this->value.clear();
int size = _Zip<ArgTypes...>::_get_size();
for(int i=0; i<size; i++){
this->value.push_back(_Zip<ArgTypes...>::_get_at(i));
}
}
std::string _get_name(){
return "zip("+_Zip<ArgTypes...>::_get_name()+")";
}
public:
Zip(Value<std::vector<ArgTypes>>*... args, const std::string& alias)
:DerivedValue<std::vector<std::tuple<ArgTypes...>>>("", alias),
_Zip<ArgTypes...>(args...) {
this->set_name(_get_name());
}
};
template<typename> class Map; // undefined
template <typename Ret, typename... ArgTypes>
class Map<Ret(ArgTypes...)> : public DerivedValue<std::vector<Ret>>{
private:
Function<Ret(ArgTypes...)>& fn;
Zip<ArgTypes...>* arg;
void update_value(){
this->value.clear();
for(auto tup : arg->get_value()){
this->value.push_back(call(fn,tup));
}
}
public:
Map(Function<Ret(ArgTypes...)>& fn, Zip<ArgTypes...>* arg, const std::string& alias)
:DerivedValue<std::vector<Ret>>("map("+fn.get_name()+":"+arg->get_name()+")", alias),
fn(fn), arg(arg){ }
};
template<typename... T> class _Tuple;
template<>
class _Tuple<> {
protected:
std::tuple<> _get_value(){
return std::make_tuple();
}
std::string _get_name(){
return "";
}
public:
_Tuple() { }
};
template<typename Head, typename... Tail>
class _Tuple<Head, Tail...> : private _Tuple<Tail...> {
protected:
Value<Head>* head;
typename std::tuple<Head,Tail...> _get_value(){
auto tail_tuple = _Tuple<Tail...>::_get_value();
return std::tuple_cat(std::make_tuple(head->get_value()),tail_tuple);
}
std::string _get_name(){
return head->get_name()+","+_Tuple<Tail...>::_get_name();
}
public:
_Tuple() { }
_Tuple(Value<Head>* head, Value<Tail>*... tail)
: _Tuple<Tail...>(tail...),
head(head) { }
};
template <typename... ArgTypes>
class Tuple : public DerivedValue<std::tuple<ArgTypes...>>,
private _Tuple<ArgTypes...>{
protected:
void update_value(){
this->value = _Tuple<ArgTypes...>::_get_value();
}
std::string _get_name(){
return "tuple("+_Tuple<ArgTypes...>::_get_name()+")";
}
public:
Tuple(Value<ArgTypes>*... args, const std::string& alias)
:DerivedValue<std::tuple<ArgTypes...>>("", alias),
_Tuple<ArgTypes...>(args...) {
this->set_name(_get_name());
}
};
template<typename> class Apply; // undefined
template <typename Ret, typename... ArgTypes>
class Apply<Ret(ArgTypes...)> : public DerivedValue<Ret>{
private:
Function<Ret(ArgTypes...)>& fn;
Tuple<ArgTypes...>* arg;
void update_value(){
auto &tup = arg->get_value();
this->value = call(fn, tup);
}
public:
Apply(Function<Ret(ArgTypes...)>& fn, Tuple<ArgTypes...>* arg, const std::string& alias)
:DerivedValue<Ret>("apply("+fn.get_name()+":"+arg->get_name()+")", alias),
fn(fn), arg(arg){ }
};
template<typename T>
class Count : public DerivedValue<int>{
private:
Function<bool(T)>& selector;
Value<std::vector<T> >* v;
void update_value(){
value = 0;
for(auto val : v->get_value()){
if(selector(val))
value++;
}
}
public:
Count(Function<bool(T)>& selector, Value<std::vector<T>>* v, const std::string alias)
:DerivedValue<int>("count("+selector.get_name()+":"+v->get_name()+")", alias),
selector(selector), v(v) { }
};
template <typename T>
class Reduce : public DerivedValue<T>{
private:
Function<T(std::vector<T>)>& reduce;
void update_value(){
this->value = reduce(v->get_value());
}
protected:
Value<std::vector<T> >* v;
public:
Reduce(Function<T(std::vector<T>)>& reduce, Value<std::vector<T> >* v, const std::string alias)
:DerivedValue<T>("reduceWith("+reduce.get_name()+":"+v->get_name()+")", alias),
reduce(reduce), v(v) { }
};
template <typename T>
class Max : public Reduce<T>{
public:
Max(Value<std::vector<T>>* v, const std::string alias)
:Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("max",
FUNC(([](std::vector<T> vec){
return *std::max_element(vec.begin(), vec.end());}))),
v, alias) { }
};
template <typename T>
class Min : public Reduce<T>{
public:
Min(Value<std::vector<T>>* v, const std::string alias)
:Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("min",
FUNC(([](std::vector<T> vec){
return *std::min_element(vec.begin(), vec.end());}))),
v, alias) { }
};
template <typename T>
class Mean : public Reduce<T>{
public:
Mean(Value<std::vector<T>>* v, const std::string alias)
:Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("mean",
FUNC(([](std::vector<T> vec){
int n = 0; T sum = 0;
for (T e : vec){ n++; sum += e; }
return n>0 ? sum / n : 0; }))),
v, alias) { }
};
template <typename T>
class Range : public Reduce<T>{
public:
Range(Value<std::vector<T>>* v, const std::string alias)
:Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("range",
FUNC(([](std::vector<T> vec){
auto minmax = std::minmax_element(vec.begin(), vec.end());
return (*minmax.second) - (*minmax.first); }))),
v, alias) { }
};
template <typename T>
class ElementOf : public Reduce<T>{
public:
ElementOf(Value<int>* index, Value<std::vector<T>>* v, const std::string alias)
:Reduce<T>(GenFunction::register_function<T(std::vector<T>)>("elementOf",
FUNC(([index](std::vector<T> vec){return vec[index->get_value()];}))),
v, alias) { }
};
template <typename T>
class ReduceIndex : public DerivedValue<std::pair<T, int> >{
private:
Function<std::pair<T,int>(std::vector<T>)>& reduce;
Value<std::vector<T> >* v;
void update_value(){
this->value = reduce(v->get_value());
}
public:
ReduceIndex(Function<std::pair<T,int>(std::vector<T>)>& reduce, Value<std::vector<T> >* v, const std::string alias="")
:DerivedValue<T>("reduceIndexWith("+reduce.get_name()+":"+v->get_name()+")", alias),
reduce(reduce), v(v) { }
};
template <typename T>
class MaxIndex : public ReduceIndex<T>{
public:
MaxIndex(Value<std::vector<T>>* v, const std::string alias="")
:ReduceIndex<T>(GenFunction::register_function<T(std::vector<T>)>("maxIndex",
FUNC(([](std::vector<T> vec){
auto elptr = std::max_element(vec.begin(), vec.end());
return std::pair<T,int>(*elptr, int(elptr-vec.begin())); }))),
v, alias) { }
};
template <typename T>
class MinIndex : public ReduceIndex<T>{
public:
MinIndex(Value<std::vector<T>>* v, const std::string alias="")
:ReduceIndex<T>(GenFunction::register_function<T(std::vector<T>)>("minIndex",
FUNC(([](std::vector<T> vec){
auto elptr = std::min_element(vec.begin(), vec.end());
return std::pair<T,int>(*elptr, int(elptr-vec.begin())); }))),
v, alias) { }
};
template <typename T>
class BoundValue : public DerivedValue<T>{
protected:
Function<T()>& f;
void update_value(){
this->value = f();
}
public:
BoundValue(Function<T()>& f, const std::string alias="")
:DerivedValue<T>(f.get_name()+"(<bound>)", alias),
f(f) { }
};
template <typename T>
class PointerValue : public DerivedValue<T*>{
protected:
void update_value(){ }
public:
PointerValue(const std::string& name, T* ptr, const std::string alias="")
:DerivedValue<T*>(name, alias){
this->value = ptr;
}
};
template <typename T>
class ConstantValue : public DerivedValue<T>{
protected:
void update_value(){ }
public:
ConstantValue(const std::string& name, T const_value, const std::string alias="")
:DerivedValue<T>("const::"+name, alias),
Value<T>::value(const_value) { }
};
}
#endif // value_hpp
fv::BoundValue::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:847
fv::Max
Find and return the maximum value of a vector.
Definition: value.hpp:726
fv::Zip
Zips a series of vectors together.
Definition: value.hpp:533
fv::Reduce
Reduce a Value of type vector<T> to just a T.
Definition: value.hpp:705
fv::Count::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:683
fv::Pair::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:457
fv::MinIndex
Find and return the minimum value of a vector and its index.
Definition: value.hpp:828
fv::BoundValue
A generic value owning only a function object.
Definition: value.hpp:844
fv::DerivedValue::get_value
T & get_value()
Calculate, if necessary, and return the value held by this object.
Definition: value.hpp:413
fv::Range
Calculate the range of the values in a vector.
Definition: value.hpp:767
fv::Tuple
Takes a series of Value objects and bundles them together into a std::tuple object.
Definition: value.hpp:631
fv::WrapperVector
A std::vector wrapper around a C-style array.
Definition: value.hpp:433
fv::ReduceIndex
Similar to Reduce, but returns a pair of a T and an int.
Definition: value.hpp:795
fv::Count
Returns the count of elements in the input vector passing a test function.
Definition: value.hpp:678
fv::MaxIndex
Find and return the maximum value of a vector and its index.
Definition: value.hpp:814
fv::Reduce::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:709
fv::GenFunction
Parent class to all Function classes.
Definition: value.hpp:98
fv::Tuple::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:634
fv::ObservedValue
A value supplied by the dataset, not derived.
Definition: value.hpp:359
fv::Min
Find and return the minimum value of a vector.
Definition: value.hpp:739
fv::Pair
Creates a std::pair type from a two other Value objects.
Definition: value.hpp:454
fv::Apply< Ret(ArgTypes...)>::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:661
fv::ObservedValue::get_value
T & get_value()
Calculate, if necessary, and return the value held by this object.
Definition: value.hpp:368
fv::ReduceIndex::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:800
fv::Map< Ret(ArgTypes...)>::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:570
fv::ConstantValue::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:878
fv
The namespace containing all filval classes and functions.
Definition: api.hpp:6
fv::ElementOf
Extract the element at a specific index from a vector.
Definition: value.hpp:781
fv::Mean
Calculate the mean value of a vector.
Definition: value.hpp:752
fv::WrapperVector::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:438
fv::Value
A generic value.
Definition: value.hpp:339
fv::Zip::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:536
fv::GenFunction::format_code
static std::string format_code(const std::string &code)
Attempt to invoke clang-format for the purpose of printing out nicely formatted functions to the log ...
Definition: value.hpp:127
log.hpp
fv::DerivedValue
A Value derived from some other Values, not directly from the dataset.
Definition: value.hpp:390
fv::PointerValue::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:863
fv::Value::get_value
virtual T & get_value()=0
Calculate, if necessary, and return the value held by this object.
fv::call
auto call(F &f, TUPLE &&t)
This calls a function of type F with the contents of the tuple as separate arguments.
Definition: value.hpp:86
fv::ConstantValue
A Value which always returns the same value, supplied in the constructor.
Definition: value.hpp:876
fv::GenFunction::function_registry
static std::map< const std::string, GenFunction * > function_registry
Static mapping of functions from their name to the object wrapper of the function.
Definition: value.hpp:110
fv::PointerValue
A Value of a pointer.
Definition: value.hpp:861