Does Phobos have some variadic algorithm to order l-value reference arguments in place? Something like
int a=3;
int b=2;
int c=1;
orderInPlace(a,b,c);
// a is now 1
// b is now 2
// c is now 3
Also a functional variant, say order(a, b, c), that returns a tuple would also be nice.
If not, I guess we should make use of std.algorithm:swap.
See also http://forum.dlang.org/thread/eweortsmcmibppmvtriw#forum.dlang.org#post-eweortsmcmibppmvtriw:40forum.dlang.org.
Adam's solution works, although it uses a temporary copy of the elements. With a small modification to std.algorithm, it's possible to write a version which sorts the elements in-place:
import std.algorithm;
import std.stdio;
import std.traits;
import std.typecons;
struct SortableRef(T)
{
private T * _p;
#property ref T value() { return *_p; }
alias value this;
void opAssign(T * value) { _p = value; }
#disable void opAssign(SortableRef!T value);
void proxySwap(SortableRef!T other) { swap(*_p, *other._p); }
}
template PointerTo(T) { alias T* PointerTo; }
void orderInPlace(T...)(ref T values)
if (!is(CommonType!(staticMap!(PointerTo, T)) == void))
{
alias CommonType!T E;
SortableRef!E[values.length] references;
foreach (i, ref v; values)
references[i] = &v;
references[].sort();
}
void main()
{
int a=3;
int b=1;
int c=2;
orderInPlace(a, b, c);
writeln([a, b, c]);
}
However, it is only practical if the values passed to orderInPlace are large, unassignable, or otherwise impractical to copy.
I don't think Phobos has one, but you could make your own kinda like this:
void orderInPlace(T...)(ref T t) {
import std.algorithm;
T[0][T.length] buffer;
foreach(idx, a; t)
buffer[idx] = a;
auto sorted = sort(buffer[]);
foreach(idx, a; t)
t[idx] = sorted[idx];
}
std.algorithm,sort needs an array, but that's easy enough - we copied the tuple into a stack array, sorted it, then copied the info back into the tuple. So maybe not perfect but it'd work. You can make it functional by just returning t instead of doing it ref.
A sorting network here is probably what would be most efficient given the low number of arguments, and the fact that their number is compile-time known (no loop conditions).
bubble sort lends itself well to being sort network'ed. I threw this together. It works and is really simple:
import std.stdio, std.string;
void bubbleSort(T...)(ref T values)
{
static if (T.length > 1)
{
foreach(I, _; T[0 .. $ - 1])
{
pragma(msg, format("[%s %s]", I, I + 1));
compareAndSwap(values[I], values[I + 1]);
}
bubbleSort(values[0 .. $ - 1]);
}
}
void compareAndSwap(T)(ref T a, ref T b)
{
import std.algorithm;
if(a > b)
swap(a, b);
}
void main()
{
int a = 10;
int b = 30;
int c = 11;
int d = 20;
int e = 4;
int f = 330;
int g = 21;
int h = 110;
shellSort(a, b, c, d, e, f, g, h);
writefln("%s %s %s %s %s %s %s %s!", a, b, c, d, e, f, g, h);
}
Although to be honest, if this was standard library, any sorting network of less than 10 arguments should be hand written.
EDIT: I completely changed the previous algorithm, which was actually highly ineficient. Bubble sort is not optimal, but it actually works OK for sorting algorithms. There's some pragmas in there to see the network that's built.
Related
I have a task to do (C++). I have quite a big function that have lot of arguments and uses a lot of different function inside. It is quite complicated. Overall, it creates a container and add values to the container depends on what is going on inside. I have to check if returned container is empty or to get its size but without calling that function with size() or empty(). (Not to create container only to check if it is empty()). I was told to create similar (almost identical) function that detects if there was something added to container. For example, something like this but with very easy example:
std::vector<int> getData(int& a, int& b, int& c) {
std::vector<int> result{};
//complicated operations replaced by simple to show a problem
for(int i=0;i<10;i++){
if(a - b > 0){
result.emplace_back(c);
}
else if ( c == 1){
return result;
}
else continue;
}
return result;
}
int getSize(int& a, int& b, int& c){
int size = 0;
//complicated operations replaced by simple to show a problem
for(int i=0;i<10;i++){
if(a - b > 0){
size++;
}
else if ( c == 1){
return size;
}
else continue;
}
return size;
}
As you can see, functions are almost identical. The real function is much bigger and code duplication is high. I am wondering if there might be a solution to that. I was told that templates might be good solution but I have no idea how should I use it. Can someone help me?
You could put the common part in a separate function template that takes a functor as an argument and supply different functors, like lambdas, inside your getData and getSize functions.
Example:
template <class Func>
void doStuff(int a, int b, int c, Func&& func) {
for (int i = 0; i < 10; i++) {
if (a - b > 0) {
func(); // call func(), the supplied functor
} else if (c == 1) {
return;
} else
continue;
}
return;
}
std::vector<int> getData(int& a, int& b, int& c) {
std::vector<int> result{};
// capture `result` and `c` in the lambda:
doStuff(a, b, c, [&result, c] { result.emplace_back(c); });
return result;
}
int getSize(int& a, int& b, int& c) {
int size = 0;
// capture `size` in the lambda:
doStuff(a, b, c, [&size] { ++size; });
return size;
}
I encountered the following issue in Eigen taking a set of elements uniformly spaced within a vector employing the class Map.
void func (int A, int B)
{
Eigen::Map<VectorXf,0,Eigen::InnerStride<B> > myMap(v.data() + B - 1, A);
}
The issue is in the 3rd argument of the template "Eigen::InnerStride". The compiler says "error: 'B' is not a constant expression".
I tried to fix as follows:
constexpr int varToConst(int arg)
{
return arg;
}
void func (int A, int B)
{
Eigen::Map<VectorXf,0,Eigen::InnerStride<varToConst(B)> > myMap(v.data() + B - 1, A);
}
but I get the same error. The int B variable is passed by the main and unfortunately, inside the main, it cannot be a const.
Thank you in advance for any help.
You can use dynamic stride, like this:
void func (int A, int B) {
Eigen::Map<VectorXf,0,Eigen::InnerStride<>> myMap(v.data() + B - 1, A, Eigen::InnerStride<>(B));
}
If this section is performance critical, and if the number of feasible B's is small (like - maybe the only valid values are B=2 and B=3), then you can also template func() on B's value. Then you would have something like template <int B> func(int A), and func<2>(/*A=*/10); at the call site.
I want to have two version a function by hiding or not hiding several lines of code at the middle and also near the end of the function with template or other means. How to do that?
The functions are performance critical. They got run a gazillion of gazillion times.
You could implement the first one with a default parameter:
int A(int a, int b, int c, int d = 0)
{
// stuff
}
You can factor out the common part and use a function object to pass the differing part:
template<class Fun>
int AB(Fun&& fun){
int x = 0;
Outer Loop{
Inner Loop{
x = std::forward<Fun>(fun)();
}
}
return x;
}
int a, b, c, d;
// ... initialize
int result1 = AB([a,b,c]{
return a + b;
});
int result2 = AB([a,b,c,d]{
return a + b + c*d;
});
You could make this even more general by templating the return type.
There are no branches and an optimizing compiler will be able to expand the function call inline. The latter is the reason to prefer function objects to function pointers.
Honestly, I would suggest you to re-implement your code. But the one thing that is coming to my mind is using function as parameter, see below (you may also use lambda expression):
int fun1(int a, int b, int c, int d) {
return a + b;
}
int fun2(int a, int b, int c, int d) {
return a + b + c*d;
}
template <int (*FUN)(int, int, int, int)> int fun_main(int a, int b, int c, int d = 0) {
int x = 0;
Outer Loop{
Inner Loop{
x += FUN(a, b, c, d);
}
}
return x;
}
Then somwhere in your code:
fun_main<fun1>(1, 2, 3, 4);
I have such piece of code:
template <class T>
struct Rgb
{
T *r, *g, *b;
Rgb(int nr, int ng, int nb)
{
r = new T(nr);
g = new T(ng);
b = new T(nb);
}
Rgb(int n)
{
Rgb(n, n, n);
}
~Rgb()
{
delete r;
delete g;
delete b;
}
};
I have done it in such way, because I want to be able to create objects like:
Rgb<std::vector<int>> a(10); // so it creates 3 vectors inside,
// each with 10 elements or
Rgb<std::deque<double>> a(2, 5, 4); // so it creates 3 deques inside
// with different sizes
But the implementation I have given above does not work. Help me please... thanks...
If you compiler supports constructor delegation (which e.g. Clang 3.2 does) you can do the following:
Rgb(int n) : Rgb(n, n, n)
{
}
What you're doing is constructing a temporary Rgb instance in the constructor, which will fail once the uninitialized r, g and b get deleted.
Otherwise I'd recommend either creating a common init function that does the initialization or simply duplicate the code. And as the comments are noting you shouldn't use new here (that's almost always a code smell in modern C++ code). Bringing this together:
template <class T>
struct Rgb
{
T r, g, b;
Rgb(int nr, int ng, int nb) : r(nr), g(ng), b(nb)
{ }
Rgb(int n) : r(n), g(n), b(n)
{ }
~Rgb()
{ }
};
I need to create a function that has a parameter which is a multi-dimensional array with two dimensions being user-specified, e.g.
int function(int a, int b, int array[a][b])
{
...
}
How would I do that in C++ ?
Are the dimensions known at compile-time? In that case, turn them into template parameters and pass the array by reference:
template<int a, int b>
int function(int(&array)[a][b])
{
...
}
Example client code:
int x[3][7];
function(x);
int y[6][2];
function(y);
Assuming the dimensions are not known at compile time, you emulate a two dimensional array with a one dimensional array:
int& getat(int x, int y, int r, int c, int *array) {return array[y*c+x];}
int function(int a, int b, int *array) {
getat(4, 2, a, b, array) = 32; //array[4,2] = 32
}
or, for safety, wrap it all in a class:
template <class T>
class array2d {
std::vector<T> data;
unsigned cols, rows;
public:
array2d() : data(), cols(0), rows(0) {}
array2d(unsigned c, unsigned r) : data(c*r), cols(c), rows(r) {}
T& operator()(unsigned c, unsigned r) {
assert(c<cols&&r<rows);
return data[r*cols+c];
}
};
or, best yet, use Boost's Multidimensional Array, which will be better than anything mere mortals could write.
I'm not sure if this work, because your question and code are not the same, according to your code the function can have 3 parameters, so this would work:
int function(int a, int b, int** &array)
{
array = new int*[a];
for (int i =0;i<a;i++)
array[i] = new int[b];
// I don't know why you are returning int, probably doing something here....
}
However your question says that your function can take only one parameter, so:
if the dimensions are known at compile time, then Fred's Answer is the best (it charmed me in fact! :) ).
if not, I can't see any possible solution that allows passing more than one user-specified value other than encapsulating all these values in one object.
Like this:
class Foo {
public:
Foo(int d1, int d2)
{ a = d1; b = d2; }
int a,b;
int** array;
};
int function(Foo &f)
{
f.array = new int*[f.a];
for (int i = 0;i<f.a;i++)
f.array[i] = new int[f.b];
// I don't know why you are returning int, probably doing something here....
}
Though I find it a bad idea, in fact the function could be a parameterless method instead:
class Foo {
public:
Foo(int d1, int d2)
{ a = d1; b = d2; }
void Create() // Or could do this right in the Constructor
{
array = new int*[a];
for (int i = 0;i<a;i++)
array[i] = new int[b];
}
private:
int a,b;
int** array;
};
Still this is a bad idea, because you are reinventing the wheel, as there are a perfect class in the STL to do all the work for you:
vector< vector<int> > v; // Now v is a 2D array