value.hpp
Go to the documentation of this file.
#ifndef value_hpp
#define value_hpp
#include <algorithm>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <sstream>
#include <tuple>
#include <typeindex>
#include <utility>
#include <vector>
#include "log.hpp"
namespace fv{
namespace detail {
template<typename T, int N, bool Done, typename... TYPES>
struct _HomoTuple {
typedef _HomoTuple<T, N, sizeof...(TYPES)+1==N, TYPES..., T> stype;
typedef typename stype::type type;
};
template<typename T, int N, typename... TYPES>
struct _HomoTuple<T, N, true, TYPES...> {
typedef std::tuple<TYPES...> type;
};
}
template<typename T, int N>
struct HomoTuple {
typedef detail::_HomoTuple<T, N, N==0> stype;
typedef typename stype::type type;
};
namespace detail {
// Convert array into a tuple
template<typename Array, std::size_t... I>
decltype(auto) a2t_impl(const Array& a, std::index_sequence<I...>){
return std::make_tuple(a[I]...);
}
}
template<typename T, std::size_t N, typename Indices = std::make_index_sequence<N>>
decltype(auto) a2t(const std::array<T, N>& a){
return detail::a2t_impl(a, Indices());
}
namespace detail {
// Convert tuple into a vector
template<typename R, typename Tuple, std::size_t... Is>
decltype(auto) t2v_impl(const Tuple& t, std::index_sequence<Is...>){
/* return std::make_tuple(a[I]...); */
return std::vector<R>({std::get<Is>(t)...});
}
}
template<typename R, typename... ArgTypes>
std::vector<R> t2v(const std::tuple<ArgTypes...>& t){
return detail::t2v_impl<R, std::tuple<ArgTypes...>>(t, std::index_sequence_for<ArgTypes...>{});
}
namespace detail {
template <class F, class Tuple, std::size_t... I>
constexpr decltype(auto) call_impl(F &&f, Tuple &&t, std::index_sequence<I...>){
return std::invoke(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...);
}
}
template <class F, class Tuple>
constexpr decltype(auto) call(F &&f, Tuple &&t){
return detail::call_impl(
std::forward<F>(f), std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{});
}
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;
}
std::string& get_impl(){
return impl;
}
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 << "FUNCTION::" << 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 T>
static Function<T>& lookup_function(const std::string& name){
if (GenFunction::function_registry[name] == nullptr){
CRITICAL("Function \"" << name << "\" not previously registered", -1);
} else {
Function<T>* func = dynamic_cast<Function<T>*>(GenFunction::function_registry[name]);
if (func == nullptr){
CRITICAL("Function \"" << name << "\" request and register have mismatched types", -1);
}
return *GenFunction::function_registry[name];
}
}
};
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
template <typename T>
class Value;
class GenValue;
typedef std::map<std::string, GenValue*> ValueSet;
class GenValue{
private:
std::string name;
protected:
bool value_valid;
void _reset(){
this->value_valid = false;
}
inline static std::map<std::pair<const std::type_index, const std::string>, GenValue*> values;
inline static std::map<std::pair<const std::type_index, const std::string>, GenValue*> aliases;
bool logging_enabled;
public:
GenValue(const std::type_index&& ti, const std::string& name, const std::string& alias)
:name(name), value_valid(false), logging_enabled(false){
if (alias != "")
INFO("Registered value: \"" << name << "\" with alias: \"" << alias << "\"");
else
INFO("Registered value: \"" << name);
values[std::make_pair(ti,name)] = this;
if (alias != "")
GenValue::alias(ti, alias, this);
}
const std::string& get_name(){
return name;
}
virtual void log() = 0;
static void reset(){
for (auto val : values){
if (val.second != nullptr){
val.second->_reset();
}
}
}
template<typename T>
static Value<T>* get_value(const std::string& name){
const std::type_index& ti = typeid(T);
auto lookup_id = std::make_pair(ti,name);
if (aliases[lookup_id] != nullptr)
return (Value<T>*)aliases[lookup_id];
else
return (Value<T>*)values[lookup_id];
}
static void alias(const std::type_index& ti, const std::string& name, GenValue* value){
auto lookup_id = std::make_pair(ti,name);
if (aliases[lookup_id] != nullptr){
WARNING("WARNING: alias \"" << name << "\" overrides previous entry.");
}
aliases[lookup_id] = value;
}
template<typename T>
static void alias(const std::string& name, Value<T>* value){
alias(typeid(T), name, value);
}
static std::string summary(){
std::stringstream ss;
ss << "The following values have been created:" << std::endl;
for (auto item : values){
auto& key = item.first;
auto& value = item.second;
if (value == nullptr) continue;
ss << "\tVALUE::\"" << key.second << "\" at address " << value << std::endl;
}
ss << "And these aliases:" << std::endl;
for (auto item : aliases){
auto& key = item.first;
auto& value = item.second;
std::string orig("VOID");
if (value == nullptr) continue;
for (auto v_item : values){
auto& v_value = v_item.second;
if (v_value == value){
orig = v_value->get_name();
break;
}
}
ss << "\tALIAS::\"" << key.second << "\" 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{
protected:
std::function<std::string(T)> value_to_string;
public:
Value(const std::string& name, const std::string& alias="")
:value_to_string([](T){return "";}),
GenValue(typeid(T), name, alias){ }
virtual T& get_value() = 0;
void enable_logging(const std::function<std::string(T)>& value_to_string = [](T){return "";}){
logging_enabled = true;
this->value_to_string = value_to_string;
}
void disable_logging(){
logging_enabled = false;
}
};
template <typename T>
class ObservedValue : public Value<T>{
private:
T *val_ref;
public:
ObservedValue(const std::string& name, T* val_ref, const std::string& alias="")
:Value<T>(name, alias),
val_ref(val_ref){ }
void log(){
if(this->logging_enabled){
INFO(this->get_name() << ": " << this->value_to_string(*val_ref));
}
}
static std::string fmt_name(const std::string& name){
return name;
}
T& get_value(){
if (!this->value_valid){
this->value_valid = true;
this->log();
}
return *val_ref;
}
};
template <typename T>
class DerivedValue : public Value<T>{
protected:
T value;
virtual void update_value() = 0;
public:
DerivedValue(const std::string& name, const std::string& alias="")
:Value<T>(name, alias){ }
void log(){
if(this->logging_enabled){
INFO(this->get_name() << ": " << this->value_to_string(value));
}
}
T& get_value(){
if (!this->value_valid){
update_value();
this->value_valid = true;
this->log();
}
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:
static std::string fmt_name(Value<int>* size, Value<T*>* data){
return "wrapper_vector("+size->get_name()+","+data->get_name()+")";
}
WrapperVector(Value<int>* size, Value<T*>* data, const std::string& alias="")
:DerivedValue<std::vector<T> >(fmt_name(size,data), 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:
static std::string fmt_name(Value<T1> *value1, Value<T2> *value2){
return "pair("+value1->get_name()+","+value2->get_name()+")";
}
Pair(Value<T1> *value1, Value<T2> *value2, const std::string alias="")
:DerivedValue<std::pair<T1, T2> >(fmt_name(value1, value2), 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){
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) { }
};
namespace impl {
std::string zip_fmt_name(){
return "";
}
template<typename Head>
std::string zip_fmt_name(Value<std::vector<Head>>* head){
return head->get_name();
}
template<typename Head1, typename Head2, typename... Tail>
std::string zip_fmt_name(Value<std::vector<Head1>>* head1, Value<std::vector<Head2>>* head2, Value<std::vector<Tail>>*... tail){
return head1->get_name() + "," + zip_fmt_name<Head2, Tail...>(head2, tail...);
}
}
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));
}
}
public:
static std::string fmt_name(Value<std::vector<ArgTypes>>*... args){
return "zip("+zip_fmt_name(args...)+")";
}
Zip(Value<std::vector<ArgTypes>>*... args, const std::string& alias)
:DerivedValue<std::vector<std::tuple<ArgTypes...>>>(fmt_name(args...), alias),
_Zip<ArgTypes...>(args...) { }
};
template<typename> class Map; // undefined
template <typename Ret, typename... ArgTypes>
class Map<Ret(ArgTypes...)> : public DerivedValue<std::vector<Ret>>{
private:
typedef Value<std::vector<std::tuple<ArgTypes...>>> arg_type;
Function<Ret(ArgTypes...)>& fn;
arg_type* arg;
void update_value(){
this->value.clear();
for(auto tup : arg->get_value()){
this->value.push_back(call(fn,tup));
}
}
public:
static std::string fmt_name(Function<Ret(ArgTypes...)>& fn, arg_type* arg){
return "map("+fn.get_name()+":"+arg->get_name()+")";
}
Map(Function<Ret(ArgTypes...)>& fn, arg_type* arg, const std::string& alias)
:DerivedValue<std::vector<Ret>>(fmt_name(fn, arg), alias),
fn(fn), arg(arg){ }
};
template<typename... T> class _Tuple;
template<>
class _Tuple<> {
protected:
std::tuple<> _get_value(){
return std::make_tuple();
}
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);
}
public:
_Tuple() { }
_Tuple(Value<Head>* head, Value<Tail>*... tail)
: _Tuple<Tail...>(tail...),
head(head) { }
};
namespace impl {
std::string tuple_fmt_name(){
return "";
}
template<typename Head>
std::string tuple_fmt_name(Value<Head>* head){
return head->get_name();
}
template<typename Head1, typename Head2, typename... Tail>
std::string tuple_fmt_name(Value<Head1>* head1, Value<Head2>* head2, Value<Tail>*... tail){
return head1->get_name() + "," + tuple_fmt_name<Head2, Tail...>(head2, tail...);
}
}
template <typename... ArgTypes>
class Tuple : public DerivedValue<std::tuple<ArgTypes...>>,
private _Tuple<ArgTypes...>{
protected:
void update_value(){
this->value = _Tuple<ArgTypes...>::_get_value();
}
public:
static std::string fmt_name(Value<ArgTypes>*... args){
return "tuple("+impl::tuple_fmt_name(args...)+")";
}
Tuple(Value<ArgTypes>*... args, const std::string& alias)
:DerivedValue<std::tuple<ArgTypes...>>(fmt_name(args...), alias),
_Tuple<ArgTypes...>(args...) { }
};
template <size_t N, typename... ArgTypes>
class DeTup : public DerivedValue<typename std::tuple_element<N, std::tuple<ArgTypes...>>::type>{
Value<std::tuple<ArgTypes...>> tup;
protected:
void update_value(){
this->value = std::get<N>(tup->get_value());
}
public:
static std::string fmt_name(Value<std::tuple<ArgTypes...>>* tup){
return "detup("+tup->get_name()+")";
}
DeTup(Value<std::tuple<ArgTypes...>>* tup, const std::string& alias)
:DerivedValue<typename std::tuple_element<N, std::tuple<ArgTypes...>>::type>(fmt_name(tup), alias),
tup(tup) { }
};
template <size_t N, typename... ArgTypes>
class DeTupVector : public DerivedValue<std::vector<typename std::tuple_element<N, std::tuple<ArgTypes...>>::type>>{
Value<std::vector<std::tuple<ArgTypes...>>>* tup;
protected:
void update_value(){
this->value.clear();
for( auto& t : tup->get_value()){
this->value.push_back(std::get<N>(t));
}
}
public:
static std::string fmt_name(Value<std::vector<std::tuple<ArgTypes...>>>* tup){
return "detup_vec("+tup->get_name()+")";
}
DeTupVector(Value<std::vector<std::tuple<ArgTypes...>>>* tup, const std::string& alias)
:DerivedValue<std::vector<typename std::tuple_element<N, std::tuple<ArgTypes...>>::type>>(fmt_name(tup), alias),
tup(tup) { }
};
template<typename> class Apply; // undefined
template <typename Ret, typename... ArgTypes>
class Apply<Ret(ArgTypes...)> : public DerivedValue<Ret>{
private:
Function<Ret(ArgTypes...)>& fn;
Value<std::tuple<ArgTypes...>>* arg;
void update_value(){
auto &tup = arg->get_value();
this->value = call(fn, tup);
}
public:
static std::string fmt_name(Function<Ret(ArgTypes...)>& fn, Value<std::tuple<ArgTypes...>>* arg){
return "apply("+fn.get_name()+":"+arg->get_name()+")";
}
Apply(Function<Ret(ArgTypes...)>& fn, Value<std::tuple<ArgTypes...>>* arg, const std::string& alias)
:DerivedValue<Ret>(fmt_name(fn,arg), 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:
static std::string fmt_name(Function<bool(T)>& selector, Value<std::vector<T>>* v){
return "count("+selector.get_name()+":"+v->get_name()+")";
}
Count(Function<bool(T)>& selector, Value<std::vector<T>>* v, const std::string alias)
:DerivedValue<int>(fmt_name(selector,v), alias),
selector(selector), v(v) { }
};
template<typename T>
class Filter : public DerivedValue<std::vector<T>>{
private:
Function<bool(T)>& filter;
Value<std::vector<T> >* v;
void update_value(){
this->value.clear();
for(auto val : v->get_value()){
if(this->filter(val))
this->value.push_back(val);
}
}
public:
static std::string fmt_name(Function<bool(T)>& filter, Value<std::vector<T>>* v){
return "filter("+filter.get_name()+":"+v->get_name()+")";
}
Filter(Function<bool(T)>& filter, Value<std::vector<T>>* v, const std::string alias)
:DerivedValue<std::vector<T>>(fmt_name(filter,v), alias),
filter(filter), v(v) { }
};
template<typename... ArgTypes>
class TupFilter : public DerivedValue<std::vector<std::tuple<ArgTypes...>>>{
private:
typedef std::vector<std::tuple<ArgTypes...>> value_type;
Function<bool(ArgTypes...)>& filter;
Value<value_type>* arg;
void update_value(){
this->value.clear();
for(auto val : arg->get_value()){
if(call(filter,val))
this->value.push_back(val);
}
}
public:
static std::string fmt_name(Function<bool(ArgTypes...)>& filter, Value<value_type>* arg){
return "tup_filter("+filter.get_name()+":"+arg->get_name()+")";
}
TupFilter(Function<bool(ArgTypes...)>& filter, Value<value_type>* arg, const std::string alias)
:DerivedValue<value_type>(fmt_name(filter, arg), alias),
filter(filter), arg(arg) { }
};
template <typename T>
class Reduce : public DerivedValue<T>{
private:
Function<T(std::vector<T>)>& reduce_fn;
void update_value(){
this->value = reduce_fn(v->get_value());
}
protected:
Value<std::vector<T> >* v;
public:
static std::string fmt_name(Function<T(std::vector<T>)>& reduce_fn, Value<std::vector<T>>* v){
return "reduce("+reduce_fn.get_name()+":"+v->get_name()+")";
}
Reduce(Function<T(std::vector<T>)>& reduce_fn, Value<std::vector<T> >* v, const std::string alias)
:DerivedValue<T>(fmt_name(reduce_fn, v), alias),
reduce_fn(reduce_fn), v(v) { }
};
template <typename T>
class Max : public Reduce<T>{
public:
static std::string fmt_name(Value<std::vector<T>>* v){
return "max("+v->get_name()+")";
}
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:
static std::string fmt_name(Value<std::vector<T>>* v){
return "min("+v->get_name()+")";
}
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:
static std::string fmt_name(Value<std::vector<T>>* v){
return "mean("+v->get_name()+")";
}
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:
static std::string fmt_name(Value<std::vector<T>>* v){
return "range("+v->get_name()+")";
}
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, int Size>
class Combinations : public DerivedValue<std::vector<typename HomoTuple<T,Size>::type>>{
private:
Value<std::vector<T>>* val;
typedef typename HomoTuple<T,Size>::type tuple_type;
void update_value(){
auto& v = val->get_value();
int data_size = v.size();
this->value.clear();
std::vector<bool> selector(data_size);
std::fill(selector.begin(), selector.begin()+std::min({Size,data_size}), true);
do {
std::array<T, Size> perm;
int idx = 0;
for (int i=0; i<data_size; i++){
if (selector[i]){
perm[idx] = v[i];
idx++;
if (idx == Size) break;
}
}
this->value.push_back(a2t(perm));
} while(std::prev_permutation(selector.begin(), selector.end()));
}
public:
static std::string fmt_name(Value<std::vector<T>>* val){
std::stringstream ss;
ss << "combinations(" << Size << "," << val->get_name() << ")";
return ss.str();
}
Combinations(Value<std::vector<T>>* val, const std::string alias="")
:DerivedValue<std::vector<tuple_type>>(fmt_name(val), alias),
val(val) { }
};
template <typename FST, typename SND>
class CartProduct : public DerivedValue<std::vector<std::tuple<FST,SND>>>{
private:
Value<std::vector<FST>>* val1;
Value<std::vector<SND>>* val2;
void update_value(){
this->value.clear();
auto& v1 = val1->get_value();
auto& v2 = val2->get_value();
for(int i=0; i<v1.size(); i++){
for(int j=0; j<v2.size(); j++){
this->value.push_back(std::tuple<FST,SND>(v1[i],v2[j]));
}
}
}
static std::string calc_name(Value<std::vector<FST>>* val1, Value<std::vector<SND>>* val2){
std::stringstream ss;
ss << "cartProduct("
<< val1->get_name() << ", " << val2->get_name()
<< ")";
return ss.str();
}
public:
static std::string fmt_name(Value<std::vector<FST>>* val1, Value<std::vector<SND>>* val2){
return "cartProduct("+val1->get_name()+", "+val2->get_name()+")";
}
CartProduct(Value<std::vector<FST>>* val1, Value<std::vector<SND>>* val2, const std::string alias="")
:DerivedValue<std::vector<std::tuple<FST,SND>>>(calc_name(val1, val2), alias),
val1(val1), val2(val2) { }
};
template <typename T>
class BoundValue : public DerivedValue<T>{
protected:
Function<T()>& f;
void update_value(){
this->value = f();
}
public:
static std::string fmt_name(Function<T()> f){
return f.get_name()+"(<bound>)";
}
BoundValue(Function<T()>& f, const std::string alias="")
:DerivedValue<T>(fmt_name(f), 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:
static std::string fmt_name(const std::string& name){
return "const::"+name;
}
ConstantValue(const std::string& name, T const_value, const std::string alias="")
:DerivedValue<T>(fmt_name(name), alias) {
this->value = const_value;
}
};
}
#endif // value_hpp
fv::Combinations::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:1113
fv::BoundValue::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:1194
fv::Max
Find and return the maximum value of a vector.
Definition: value.hpp:976
fv::Zip
Zips a series of vectors together.
Definition: value.hpp:662
fv::Reduce
Reduce a Value of type vector<T> to just a T.
Definition: value.hpp:951
fv::Count::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:869
fv::Pair::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:567
fv::MinIndex
Find and return the minimum value of a vector and its index.
Definition: value.hpp:1094
fv::Combinations
Find combinations of items from an input vector.
Definition: value.hpp:1108
fv::BoundValue
A generic value owning only a function object.
Definition: value.hpp:1191
fv::DerivedValue::get_value
T & get_value()
Calculate, if necessary, and return the value held by this object.
Definition: value.hpp:518
fv::Range
Calculate the range of the values in a vector.
Definition: value.hpp:1029
fv::DeTupVector::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:816
fv::Tuple
Takes a series of Value objects and bundles them together into a std::tuple object.
Definition: value.hpp:770
fv::WrapperVector
A std::vector wrapper around a C-style array.
Definition: value.hpp:539
std
STL namespace.
fv::ReduceIndex
Similar to Reduce, but returns a pair of a T and an int.
Definition: value.hpp:1061
fv::Count
Returns the count of elements in the input vector passing a test function.
Definition: value.hpp:864
fv::MaxIndex
Find and return the maximum value of a vector and its index.
Definition: value.hpp:1080
fv::Reduce::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:955
fv::GenFunction
Parent class to all Function classes.
Definition: value.hpp:139
fv::Tuple::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:773
fv::TupFilter::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:926
fv::ObservedValue
A value supplied by the dataset, not derived.
Definition: value.hpp:450
fv::Filter
Returns the elements in a vector that pass a test function.
Definition: value.hpp:891
fv::DeTup
Gets the Nth element from a tuple value.
Definition: value.hpp:791
fv::Min
Find and return the minimum value of a vector.
Definition: value.hpp:993
fv::DeTupVector
Creates a vector of extracting the Nth value from each entry in a vector of tuples.
Definition: value.hpp:813
fv::Pair
Creates a std::pair type from a two other Value objects.
Definition: value.hpp:564
fv::a2t
decltype(auto) a2t(const std::array< T, N > &a)
Converts a std::array to a std::tuple.
Definition: value.hpp:95
fv::Apply< Ret(ArgTypes...)>::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:844
fv::ObservedValue::get_value
T & get_value()
Calculate, if necessary, and return the value held by this object.
Definition: value.hpp:469
fv::ReduceIndex::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:1066
fv::Map< Ret(ArgTypes...)>::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:698
fv::ConstantValue::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:1230
fv
The namespace containing all filval classes and functions.
Definition: api.hpp:46
fv::ElementOf
Extract the element at a specific index from a vector.
Definition: value.hpp:1047
fv::call
decltype(auto) constexpr call(F &&f, Tuple &&t)
Call a function f with the elements of the tuple t as arguments.
Definition: value.hpp:127
fv::TupFilter
Returns the elements in a vector that pass a test function.
Definition: value.hpp:920
fv::Mean
Calculate the mean value of a vector.
Definition: value.hpp:1010
fv::WrapperVector::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:544
fv::Value
A templated value.
Definition: value.hpp:265
fv::CartProduct
Calculate the cartesian product of two input vectors.
Definition: value.hpp:1151
fv::CartProduct::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:1156
fv::Zip::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:665
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:172
log.hpp
fv::DerivedValue
A Value derived from some other Values, not directly from the dataset.
Definition: value.hpp:495
fv::Filter::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:896
fv::PointerValue::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:1215
fv::t2v
std::vector< R > t2v(const std::tuple< ArgTypes... > &t)
Converts a std::tuple to a std::vector.
Definition: value.hpp:112
fv::Value::get_value
virtual T & get_value()=0
Calculate, if necessary, and return the value held by this object.
fv::ConstantValue
A Value which always returns the same value, supplied in the constructor.
Definition: value.hpp:1228
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:151
fv::PointerValue
A Value of a pointer.
Definition: value.hpp:1213
fv::DeTup::update_value
void update_value()
Updates the internal value.
Definition: value.hpp:794