For Learning Purposes:
I am creating a small numerical methods library and I am trying to implement the gradient currently I have done 2D gradient and 3D gradient . But I want to generalize this to higher dimensions.
Currently I have :
matrix<double> analysis::gradient_2D(std::function<double(double, double)> fn, double x, double y)
{
matrix<double> R(2, 1);
std::function<double(double)> fnX = [fn, y](double xVar){ return fn(xVar, y); };
std::function<double(double)> fnY = [fn, x](double yVar){ return fn(x, yVar); };
R(1, 1) = differentiateBest(fnX, x);
R(1, 2) = differentiateBest(fnY, y);
return R;
}
matrix<double> analysis::gradient_3D(std::function<double(double, double, double)> fn, double x, double y, double z)
{
matrix<double> R(3, 1);
std::function<double(double)> fnX = [fn, y, z](double xVar){ return fn(xVar, y,z); };
std::function<double(double)> fnY = [fn, x, z](double yVar){ return fn(x ,yVar, z); };
std::function<double(double)> fnZ = [fn, x, y](double zVar){ return fn(x, y, zVar); };
R(1, 1) = differentiateBest(fnX, x);
R(1, 2) = differentiateBest(fnY, y);
R(1, 3) = differentiateBest(fnZ, z);
return R;
}
// Where
double analysis::differentiateBest(std::function<double(double)> fn, double x)
{
return derivative_1_Richardson_6O(fn, x);
}
// For brevity , derivative_1_Richardson_6O also has the same input as differentiateBest
I know it is verbose , but I like it
Question
What I would like to do is to create a
// What do I do at the ... ?
matrix<double> analysis::gradient_ND(std::function<double(...)> fn, matrix<double>)
So that I can pass a std::function with arbitrary input say N and I will pass
a vector which has N values.
How will I go about doing this ? If the answer is too long , links will be appreciated too .
Thank you.
PS: I saw a method using Templates , but if I use templates in the implementation , the I will have to change the .cpp file to something else right ? I would like to avoid. If using templates is the only way , then I will have to compromise. Thanks.
template<class T>
struct array_view {
T* b = nullptr; T* e = nullptr;
T* begin() const { return b; }
T* end() const { return e; }
size_t size() const { return end()-begin(); }
bool empty() const { return begin()==end(); }
T& front()const{return *begin(); }
T& back()const{return *std::prev(end()); }
T& operator[](size_t i)const{return begin()[i]; }
array_view( T* s, T* f ):b(s),e(f) {};
array_view() = default;
array_view( T* s, size_t l ):array_view(s, s+l) {}
using non_const_T = std::remove_const_t<T>;
array_view( std::initializer_list<non_const_T> il ):
array_view(il.begin(), il.end()) {}
template<size_t N>
array_view( T(&arr)[N] ):array_view(arr, N){}
template<size_t N>
array_view( std::array<T,N>&arr ):array_view(arr.data(), N){}
template<size_t N>
array_view( std::array<non_const_T,N> const&arr ):
array_view(arr.data(), N){}
template<class A>
array_view( std::vector<T,A>& v):
array_view(v.data(), v.size()){}
template<class A>
array_view( std::vector<non_const_T,A> const& v):
array_view(v.data(), v.size()){}
};
an array_view is a non-owning view into a contiguous array of T. It has converting constructors from a myriad of contiguous containers (if matrix is contiguous, a converter to array_view should be written).
Then:
matrix<double> analysis::gradient_ND(std::function<double(array_view<const double>)>, array_view<const double> pt)
is reasonable.
Using array_view causes no problem with .h and .cpp code splitting. The only templates involved are either fixed (the array_view itself), or are resolved when constructing the array_view.
matrix<double> R(pt.size(), 1);
auto make_tmp = [pt]{
std::vector<double> tmp;
tmp.reserve(pt.size());
for (double x:pt)
tmp.push_back(x);
return tmp;
};
std::vector<std::function<double(double)>> partials;
partials.reserve(pt.size());
for (size_t i = 0; i < pt.size(); ++i) {
partials.push_back(
[&,i](double x){ auto tmp=make_tmp(); tmp[i]=x; return fn(tmp); };
);
}
for (size_t i = 0; i < pt.size(); ++i) {
R(1, i) = differentiateBest(partials[i], pt[i]);
}
return R;
note that creating array of partials is not actually needed. You could just directly differentiateBest.
There is an inefficiency where partials reallocate each call. If you are ok with making reentrancy not work (which will often be ok), creating a tmp and capturing it by-value, and modifying and restoring it after each call to fn, would boost performance.
[&,i,tmp=make_tmp()](double x){ std::swap(tmp[i],x); double r=fn(tmp); std::swap(tmp[i],x); return r; };
is C++14 version. C++11 version would create a tmp variable and capture it by-value.
Related
I am learning C++11 and I would like to create copies of columns for a simple matrix template I created. I don't want to use full-fledged matrix templates like armadillo and others because I don't need sofisticated matrix algebra. The operations I would like to do are:
matrix<int> A(3,3,{1,0,1,2,2,2,1,0,1});
matrix<int> A1(3,1));
A1 = A.col_cpy(1);
// do something with the column vector
A1[2] += 5;
// and then assign back
A.col(1) = A1;
my naive first attempt with col_cpy was to return a column matrix which is wrong because the local variable is destroyed.
template<typename T >
class matrix {
T* m_elems;
size_t m_rows;
size_t m_cols;
public:
matrix(size_t rows, size_t cols)
: m_elems((T*)std::malloc(rows * cols * sizeof(T))), m_rows(rows), m_cols(cols) {}
matrix(size_t rows, size_t cols, std::initializer_list<T> const& xs)
: m_elems((T*)std::malloc(rows * cols * sizeof(T))), m_rows(rows), m_cols(cols) {
T* es = m_elems;
for (auto x : xs) {
*es = x;
++es;
}
}
auto col_cpy(size_t col) const -> T* {
auto c = (T*)std::malloc(m_rows * sizeof(T));
col_cpy(col, c);
return c;
}
auto col_cpy(size_t col) const -> matrix& {
matrix <T> c(m_rows,1);
for(auto i=0u; i<m_rows; i++)
c(i) = m_elems[col * m_rows + i];
return c;
}
Another way was to create a friend function and pass matrix by reference
template<typename T>
void col_cpy( size_t col, matrix<T> const& D, matrix<T> & A ) {
A(D.m_rows,1);
D.col_cpy(col,A.m_elems);
}
So I could do
col_cpy(1,A,A1);
It works but I think is not the safest neither elegant way to do it.
The full example is here http://coliru.stacked-crooked.com/a/546db2c1b520bdc7
Is it possible to loop over sub range using range based for loop ?
std::vector <std::string> inputs={"1","abaaaa","abc","cda"};
for (auto &it : new_vector(inputs.begin()+1, inputs.end()))
{
// …
}
You could use Boost's iterator_range:
for (auto &it : boost::make_iterator_range(inputs.begin()+1, inputs.end()))
{
cout << it << endl;
}
demo
Alternatively you could write your own wrapper.
Unfortunately, there is no such thing in the C++ standard library. However, you can define your own wrapper like this (requires at least C++ 11 - which should not be problem in 2021):
template<typename Iter>
struct range
{
Iter b, e;
Iter begin() const { return b; }
Iter end() const { return e; }
};
template<typename T>
auto slice(const T& c, std::size_t from, std::size_t to = -1) -> range<decltype(c.begin())>
{
to = (to > c.size() ? c.size() : to);
return range<decltype(c.begin())>{c.begin() + from, c.begin() + to};
}
And then you can use it:
std::vector<int> items(100);
// Iterates from 4th to 49th item
for (auto x: slice(items, 4, 50))
{
}
// Iterates from 15th to the last item
for (auto x: slice(items, 15))
{
}
tl;dr
Long story short, you #include <range/v3/view/subrange.hpp> and change your new_vector to ranges::subrange. And that's it. Demo on Compiler Explorer.
So
Given the name you imagine for this function, new_vector, maybe you think you need the entity on the right of : to be a std::vector or at least some type of container.
If that's the case, then change your mind, it's not needed. All that : wants from its "right hand side" is that it have begin and end defined on them, member or non member. For instance, this compiles and runs just fine:
struct A {};
int* begin(A);
int* end(A);
struct B {
int* begin();
int* end();
};
int main()
{
for (auto it : A{}) {}
for (auto it : B{}) {}
}
I want to create a set (mathematically speaking, not std::set) of unique elements in C++. My elements are std::pair<int, int> and they represent an edge. Because those edges are not directed, I don't want to have duplicates like (3,4) and (4,3). How can I achieve this in C++ ?
Something along these lines, perhaps:
using Edge = std::pair<int, int>;
struct CompareEdges {
bool operator()(const Edge& a, const Edge& b) const {
return Normalize(a) < Normalize(b);
}
private:
Edge Normalize(const Edge& e) {
if (e.first <= e.second) return e;
return {e.second, e.first};
}
};
std::set<Edge, CompareEdges> SetOfEdges;
This is another solution, with the compare function as lambda expression.
using Edge = pair<int, int>;
std::set<Edge, std::function<bool(const Edge &, const Edge &)>> edges(
[](const Edge &a, const Edge &b)
{
const int x = min(a.first, a.second);
const int y = min(b.first, b.second);
if (x < y)
return true;
else if (y > x)
return false;
else
return max(a.first, a.second) < max(b.first, b.second);
}
);
This is more a kind of theoretical question. Is it possible in C++11 to combine functions into a new function? For example :
auto f = [](int i){return i * 2;};
auto g = [](int i){return i + 10;};
So this works:
auto c = f(g(20)); // = 60
But I want an object that stores the combination, like
auto c = f(g);
std::cout << c(20) << std::endl; //prints 60
Edit:
Additionally what i want to create is a function a, which you can give a function b and an int n, and which returns the n'th combination of the given function b. For example (not compilable)
template<typename T>
auto combine(T b, int i) -> decltype(T)
{
if (i == 0)
return b;
return combine(b, i - 1);
}
auto c = combine(f, 2); //c = f(f(f(int)))
A first attempt:
template<class First, class Second>
auto compose( Second&& second, First&& first ) }
return [second = std::forward<Second>(second), first=std::forward<First>(first)]
(auto&&...args)->decltype(auto) {
return second( first( decltype(args)(args)... ) );
};
}
template<class A, class B, class...Rest>
auto compose(A&& a, B&& b, Rest&&... rest) {
return compose( compose(std::forward<A>(a), std::forward<B>(b)), std::forward<Rest>(rest)... );
}
template<class A>
std::decay_t<A> compose(A&& a) {
return std::forward<A>(a);
}
in C++14. Now, this isn't perfect, as the pattern doesn't work all that well in C++.
To do this perfectly, we'd have to take a look at compositional programming. Here, functions interact with an abstract stack of arguments. Each function pops some number of arguments off the stack, then pops some number back on.
This would allow you do do this:
compose( print_coord, get_x, get_y )
where get_x and get_y consume nothing but return a coordinate, and print_coord takes two coordinates and prints them.
To emulate this in C++, we need some fancy machinery. Functions will return tuples (or tuple-likes?), and those values will be "pushed onto the argument stack" logically.
Functions will also consume things off this argument stack.
At each invocation, we unpack the current tuple of arguments, find the longest collection that the function can be called with, call it, get its return value, unpack it if it is a tuple, and then stick any such returned values back on the argument stack.
For this more advanced compose to compose with itself, it then needs SFINAE checks, and it needs to be able to take a invokable object and a tuple of arguments and find the right number of arguments to call the invokable object with, plus the left-over arguments.
This is a tricky bit of metaprogramming that I won't do here.
The second part, because I missed it the first time, looks like:
template<class F>
auto function_to_the_power( F&& f, unsigned count ) {
return [f=std::forward<F>(f),count](auto&& x)
-> std::decay_t< decltype( f(decltype(x)(x)) ) >
{
if (count == 0) return decltype(x)(x);
auto r = f(decltype(x)(x));
for (unsigned i = 1; i < count; ++i) {
r = f( std::move(r) );
}
return r;
};
}
This uses no type erasure.
Test code:
auto f = [](int x){ return x*3; };
auto fs = std::make_tuple(
function_to_the_power( f, 0 ),
function_to_the_power( f, 1 ),
function_to_the_power( f, 2 ),
function_to_the_power( f, 3 )
);
std::cout << std::get<0>(fs)(2) << "\n";
std::cout << std::get<1>(fs)(2) << "\n";
std::cout << std::get<2>(fs)(2) << "\n";
std::cout << std::get<3>(fs)(2) << "\n";
prints:
2
6
18
54
You can write something along the lines of:
#include <functional>
#include <iostream>
template<class F>
F compose(F f, F g)
{
return [=](int x) { return f(g(x)); };
}
int main()
{
std::function<int (int)> f = [](int i) { return i * 2; };
std::function<int (int)> g = [](int i) { return i + 10; };
auto c = compose(f, g);
std::cout << c(20) << '\n'; // prints 60
}
The code can be simply extended to cover the second half of the question:
template<class F>
F compose(F f, unsigned n)
{
auto g = f;
for (unsigned i = 0; i < n; ++i)
g = compose(g, f);
return g;
}
int main()
{
std::function<int (int)> h = [](int i) { return i * i; };
auto d = compose(h, 1);
auto e = compose(h, 2);
std::cout << d(3) << "\n" // prints 81
<< e(3) << "\n"; // prints 6561
}
NOTE. Here using std::function. It isn't a lambda but wraps a lambda with a performance cost.
It is kind of exasperating that std collections don't provide a functional map interface to fill a collection
std::vector< int > oldV = {1,3,5};
std::vector< int > newV = (oldV % [&](int v)-> int{ return v+1; });
newV.insert( oldV.begin(), oldV.end(), [&](int v)-> int{ return 2*v; });
Is there a simple header library that implements wrappers for functional style programming with std collections?
I don't see a way to do it such that it would apply both to things like std::vector and std::unordered_set without repeating the operator definition for each container. In the case of vector it would be like this:
#include <iostream>
#include <vector>
template <typename T, typename Lambda>
std::vector< T > operator |(const std::vector< T >& input, Lambda map)
{
std::vector< T > output;
for (const T& elem : input)
output.push_back( map(elem) );
return std::move(output);
};
int main()
{
std::vector< int > oldV = {1,3,5};
std::vector< int > newV = oldV | [&](int v) -> int { return v + 1; };
for(int i=0; i< newV.size() ; i++)
{
std::cout << newV[i] << std::endl;
}
};
For the case of std::unordered_set you would only have to replace push_back with insert
The pipe operator here has the same well known semantics as on Unix/Linux shells and some languages
You could use std::generate and std::transform to do this.