Commit 8d70ecfa authored by Tobias WEBER's avatar Tobias WEBER
Browse files

array functions

parent f83a91fb
......@@ -115,6 +115,11 @@ std::shared_ptr<Symbol> Symbol::add(const Symbol &sym1, const Symbol &sym2)
return nullptr;
}
std::shared_ptr<Symbol> Symbol::add(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2)
{
return Symbol::add(*sym1, *sym2);
}
/**
* subtraction of symbols
......@@ -146,6 +151,11 @@ std::shared_ptr<Symbol> Symbol::sub(const Symbol &sym1, const Symbol &sym2)
return nullptr;
}
std::shared_ptr<Symbol> Symbol::sub(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2)
{
return Symbol::sub(*sym1, *sym2);
}
/**
* multiplication of symbols
......@@ -196,6 +206,11 @@ std::shared_ptr<Symbol> Symbol::mul(const Symbol &sym1, const Symbol &sym2)
arrNew.emplace_back(Symbol::mul(*arr[idx], sym2));
return std::make_shared<SymbolList>(arrNew, false);
}
if(sym1.GetType()==SymbolType::ARRAY && sym2.GetType()==SymbolType::ARRAY)
{ // [1,2,3] * [1,2,3]
return func_dot(std::make_shared<SymbolList>(dynamic_cast<const SymbolList&>(sym1)),
std::make_shared<SymbolList>(dynamic_cast<const SymbolList&>(sym2)));
}
else if(sym1.GetType()==SymbolType::REAL && sym2.GetType()==SymbolType::DATASET)
{ // 3 * data
return std::make_shared<SymbolDataset>(
......@@ -212,6 +227,11 @@ std::shared_ptr<Symbol> Symbol::mul(const Symbol &sym1, const Symbol &sym2)
return nullptr;
}
std::shared_ptr<Symbol> Symbol::mul(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2)
{
return Symbol::mul(*sym1, *sym2);
}
/**
* division of symbols
......@@ -242,6 +262,11 @@ std::shared_ptr<Symbol> Symbol::div(const Symbol &sym1, const Symbol &sym2)
return nullptr;
}
std::shared_ptr<Symbol> Symbol::div(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2)
{
return Symbol::div(*sym1, *sym2);
}
/**
* modulo of symbols
......@@ -614,6 +639,11 @@ std::shared_ptr<Symbol> CliASTCall::Eval(CliParserContext& ctx) const
t_real funcval = (*iter->second)(dynamic_cast<SymbolReal&>(*args[0]).GetValue());
return std::make_shared<SymbolReal>(funcval);
}
else if(auto iter = g_funcs_arr_1arg.find(ident);
iter != g_funcs_arr_1arg.end() && args[0]->GetType() == SymbolType::ARRAY)
{ // array function
return (*iter->second)(*reinterpret_cast<std::shared_ptr<SymbolList>*>(&args[0]));
}
else
{
ctx.PrintError("No suitable one-argument function \"", ident, "\" was found.");
......@@ -622,16 +652,26 @@ std::shared_ptr<Symbol> CliASTCall::Eval(CliParserContext& ctx) const
}
else if(args.size() == 2) // function call with two arguments requested
{
// real function
if(auto iter = g_funcs_real_2args.find(ident);
if(auto iter = g_funcs_gen_2args.find(ident); iter != g_funcs_gen_2args.end())
{ // general function
return (*iter->second)(args[0], args[1]);
}
else if(auto iter = g_funcs_real_2args.find(ident);
iter != g_funcs_real_2args.end() &&
args[0]->GetType() == SymbolType::REAL && args[1]->GetType() == SymbolType::REAL)
{
{ // real function
t_real arg1 = dynamic_cast<SymbolReal&>(*args[0]).GetValue();
t_real arg2 = dynamic_cast<SymbolReal&>(*args[1]).GetValue();
t_real funcval = (*iter->second)(arg1, arg2);
return std::make_shared<SymbolReal>(funcval);
}
else if(auto iter = g_funcs_arr_2args.find(ident);
iter != g_funcs_arr_2args.end()
&& args[0]->GetType() == SymbolType::ARRAY && args[1]->GetType() == SymbolType::ARRAY)
{ // array function
return (*iter->second)(*reinterpret_cast<std::shared_ptr<SymbolList>*>(&args[0]),
*reinterpret_cast<std::shared_ptr<SymbolList>*>(&args[1]));
}
else
{
ctx.PrintError("No suitable two-argument function \"", ident, "\" was found.");
......
......@@ -132,6 +132,11 @@ public:
static std::shared_ptr<Symbol> mod(const Symbol &sym1, const Symbol &sym2);
static std::shared_ptr<Symbol> pow(const Symbol &sym1, const Symbol &sym2);
static std::shared_ptr<Symbol> add(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2);
static std::shared_ptr<Symbol> sub(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2);
static std::shared_ptr<Symbol> mul(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2);
static std::shared_ptr<Symbol> div(std::shared_ptr<Symbol> sym1, std::shared_ptr<Symbol> sym2);
static const std::string& get_type_name(const Symbol &sym);
};
......@@ -148,6 +153,7 @@ public:
virtual SymbolType GetType() const override { return SymbolType::REAL; }
t_real_cli GetValue() const { return m_val; }
void SetValue(t_real_cli val) { m_val = val; }
virtual std::shared_ptr<Symbol> copy() const override { return std::make_shared<SymbolReal>(m_val); }
virtual void print(std::ostream& ostr) const override { ostr << GetValue(); }
......@@ -183,6 +189,11 @@ public:
SymbolList() = default;
SymbolList(const std::vector<std::shared_ptr<Symbol>>& val, bool islist=1) : m_val(val), m_islist(islist) {}
SymbolList(std::vector<std::shared_ptr<Symbol>>&& val, bool islist=1) : m_val(val), m_islist(islist) {}
SymbolList(const std::initializer_list<std::shared_ptr<Symbol>>& lst, bool islist=1) : m_islist(islist)
{
for(auto iter = lst.begin(); iter !=lst.end(); ++iter)
m_val.push_back(*iter);
}
virtual ~SymbolList() {}
virtual SymbolType GetType() const override { return m_islist ? SymbolType::LIST : SymbolType::ARRAY; }
......
......@@ -91,6 +91,7 @@ static std::shared_ptr<Symbol> func_typeof(std::shared_ptr<Symbol> sym)
return std::make_shared<SymbolString>(ty);
}
/**
* map of general functions with one argument
*/
......@@ -98,6 +99,84 @@ std::unordered_map<std::string, std::shared_ptr<Symbol>(*)(std::shared_ptr<Symbo
{
std::make_pair("typeof", &func_typeof),
};
/**
* map of general functions with two arguments
*/
std::unordered_map<std::string, std::shared_ptr<Symbol>(*)(std::shared_ptr<Symbol>, std::shared_ptr<Symbol>)> g_funcs_gen_2args =
{
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/**
* dot product
*/
std::shared_ptr<Symbol> func_dot(std::shared_ptr<SymbolList> sym1, std::shared_ptr<SymbolList> sym2)
{
std::shared_ptr<Symbol> symDot = std::make_shared<SymbolReal>(0);
const auto& arr1 = sym1->GetValue();
const auto& arr2 = sym2->GetValue();
for(std::size_t idx=0; idx<(arr1.size(), arr2.size()); ++idx)
symDot = Symbol::add(symDot, Symbol::mul(arr1[idx], arr2[idx]));
return symDot;
}
/**
* cross product
*/
std::shared_ptr<Symbol> func_cross(std::shared_ptr<SymbolList> sym1, std::shared_ptr<SymbolList> sym2)
{
SymbolReal symCross(0);
const auto& arr1 = sym1->GetValue();
const auto& arr2 = sym2->GetValue();
if(arr1.size() != 3 && arr2.size() != 3)
return nullptr;
// components
std::vector<std::shared_ptr<Symbol>> vec;
vec.emplace_back(Symbol::sub(Symbol::mul(arr1[1], arr2[2]), Symbol::mul(arr1[2], arr2[1])));
vec.emplace_back(Symbol::sub(Symbol::mul(arr1[2], arr2[0]), Symbol::mul(arr1[0], arr2[2])));
vec.emplace_back(Symbol::sub(Symbol::mul(arr1[0], arr2[1]), Symbol::mul(arr1[1], arr2[0])));
return std::make_shared<SymbolList>(vec, false);
}
/**
* norm
*/
std::shared_ptr<Symbol> func_norm(std::shared_ptr<SymbolList> sym)
{
// dot
auto symDot = func_dot(sym, sym);
// sqrt
return Symbol::pow(*symDot, SymbolReal(0.5));
}
/**
* map of general functions with one argument
*/
std::unordered_map<std::string, std::shared_ptr<Symbol>(*)(std::shared_ptr<SymbolList>)> g_funcs_arr_1arg =
{
std::make_pair("norm", &func_norm),
};
/**
* map of general functions with two arguments
*/
std::unordered_map<std::string, std::shared_ptr<Symbol>(*)(std::shared_ptr<SymbolList>, std::shared_ptr<SymbolList>)> g_funcs_arr_2args =
{
std::make_pair("dot", &func_dot),
std::make_pair("cross", &func_cross),
};
// ----------------------------------------------------------------------------
......
......@@ -20,11 +20,21 @@
extern std::unordered_map<std::string, t_real_cli(*)(t_real_cli)> g_funcs_real_1arg;
extern std::unordered_map<std::string, t_real_cli(*)(t_real_cli, t_real_cli)> g_funcs_real_2args;
// array functions
extern std::unordered_map<std::string, std::shared_ptr<Symbol>(*)(std::shared_ptr<SymbolList>)> g_funcs_arr_1arg;
extern std::unordered_map<std::string, std::shared_ptr<Symbol>(*)(std::shared_ptr<SymbolList>, std::shared_ptr<SymbolList>)> g_funcs_arr_2args;
// general functions
extern std::unordered_map<std::string, std::shared_ptr<Symbol>(*)(std::shared_ptr<Symbol>)> g_funcs_gen_1arg;
extern std::unordered_map<std::string, std::shared_ptr<Symbol>(*)(std::shared_ptr<Symbol>, std::shared_ptr<Symbol>)> g_funcs_gen_2args;
// constants
extern std::unordered_map<std::string, t_real_cli> g_consts_real;
// functions which are also needed in other modules
extern std::shared_ptr<Symbol> func_dot(std::shared_ptr<SymbolList> sym1, std::shared_ptr<SymbolList> sym2);
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment