Retuning multiple vectors from a function in c++? - c++

I want to return multiple vectors from a function.
I am not sure either tuple can work or not. I tried but is not working.
xxx myfunction (vector<vector<float>> matrix1 , vector<vector<float>> matrix2) {
// some functional code: e.g.
// vector<vector<float>> matrix3 = matrix1 + matrix2;
// vector<vector<float>> matrix4 = matrix1 - matrix2;
return matrix3, matrix4;

If these matrices are very small then this approach might be OK, but generally I would not do it this way. First, regardless of their size, you should pass them in by const reference.
Also, std::vector<std::vector<T>> is not a very good "matrix" implementation - much better to store the data in a contiguous block and implement element-wise operations over the entire block. Also, if you are going to return the matrices (via a pair or other class) then you'll want to look into move semantics as you don't want extra copies.
If you are not using C++11 then I'd pass in matrices by reference and fill them in the function; e.g.
using Matrix = std::vector<std::vector<float>>; // or preferably something better
void myfunction(const Matrix &m1, const Matrix &m2, Matrix &diff, Matrix &sum)
{
// sum/diff clear / resize / whatever is appropriate for your use case
// sum = m1 + m2
// diff = m1 - m2
}
The main issue with functional style code, e.g. returning std::tuple<Matrix,Matrix> is avoiding copies. There are clever things one can here to avoid extra copies but sometimes it is just simpler, IMO, to go with a less "pure" style of coding.

For Matrices, I normally create a Struct or Class for it that has these vectors, and send objects of that class in to the function. It would also help to encapsulate Matrix related operations inside that Class.
If you still want to use vector of vector, here is my opinion. You could use InOut parameters using references/pointers : Meaning, if the parameters can be updated to hold results of calculation, you would be sending the arguments in, and you would not have to return anything in that case.
If the parameters need to be const and cannot be changed, then I normally send In parameters as const references, and separate Out parameters in the function argument list itself.
Hope this helps a bit.

Related

Arguments for custom unary/binaryExpr() eigen3

I'm trying to eliminate nested for loops by making use of coefficient-wise operations on eigen3 objects. In order to achieve this I have to generalize an already existing function such that I can make us of custom coefficient-wise operations.
I found that eigen provides two functions, unaryExpr() and binaryExpr() (documentation), that allow to implement a custom coefficient-wise operation on eigen Arrays. However, as far as I understand, you can only give one or two arguments to these functions which represent the coefficients from the array itself. I would like to pass other arguments as well to this function since I need these other arguments to complete the calculation.
I would like to generalize the following function
inline Complex expValue(int twoMS, int twoMSPrime, const Matrix2cd& mat)
{
const Vector2cd& bra = getSpinBasisState(twoMSPrime);
const Vector2cd& ket = getSpinBasisState(twoMS);
return bra.adjoint()*mat*ket;
}
All the possible combinations of values for twoMS and twoMSPrime I have stored in an array like this
Eigen::ArrayXXd spinCGPart(16, 2);
So, 16 different combinations and two columns, one for twoMS and one for twoMSPrime.
Instead of looping over all the different combinations, I would like to implement a coefficient-wise operation like so
Eigen::ArrayXXcd result(16, 1);
result = spinCGPart.col(0).binaryExpr(spinCGPart.col(1), generalExpVal);
Where generalExpVal should be something like
complex generalExpVal(int a, int b, const Matrix2cd& mat) const
{
const Vector2cd& bra = getSpinBasisState(b);
const Vector2cd& ket = getSpinBasisState(a);
return bra.adjoint()*mat*ket;
}
I'm stuck with implementing this last function. The documentation for the binaryExpr() looks like it doesn't allow extra parameters to be given to the function. Is this the case? I need to pass mat as an argument since it changes constantly throughout the calculation. Any suggestion regarding eigen or another way of thinking about the problem would be very helpful and appreciated!
Still not sure what you are actually trying to achieve here, but the easiest way (with C++11 or later) to refer to additional objects in your binary functor is to use a lambda expression:
result = spinCGPart.col(0).binaryExpr(spinCGPart.col(1),
[&](int a, int b){return generalExpVal(a,b,mat);});
Fully compiling example: https://godbolt.org/z/PBJJRW
With C++03 you can manually do that using a helper struct, or using e.g., boost::bind.

std::vector<float> to std::vector<glm::vecX> without copying

I am writing a small toy game engine using Tinyobjloader for loading .obj files. I store the vertex data and everything using glm::vecX to make things easier.
Tinyobjloader gives me an std::vector<float>, when I want an std::vector<glm::vecX>. How would I do this without copying?
To be clear, a glm::vecX is a simple struct containing, for example, the float members x, y, z.
I was thinking that since structs can behave a bit like arrays, that std::move would work, but no luck.
Thanks!
Edit:
I know I wasn't clear about this, sorry. I would like to either move the std::vector<float> into an std::vector<glm::vecX> or pass it as a std::vector<glm::vecX>&.
Copying the data using std::memcpy works fine, but it copies the data, which I would like to avoid.
It may be possible to directly interpret the contents of the vector as instances of the struct, without having to copy the data. If you can guarantee the representation is compatible, that is. The contents of a vector<float> are laid out in memory as a sequence of float values directly following each other (an array) with no extra padding, while the contents of a vector<glm::vecX> are laid out as a sequence of vecX. Thus, you need to ensure the following conditions hold:
That glm::vecX is exactly the size of X floats, with no padding. Depending on the declaration of the struct, this may be platform-dependant.
That the contents of the vector<float> are in the correct sequence, i.e. as [x1,y1,z1, x2,y2,z2, ...] for a vec3 instead of [x1,x2,...,xN,y1,y2...].
In that case, you can safely reinterpret the data pointer of the float vector as pointer to an array of vecX as in this example:
std::vector<float> myObjData = ...;
auto nVecs = myObjData.size() / 3; // You should check that there are no remainders!
glm::vec3* vecs = reinterpret_cast<glm::vec3*>(myObjData.data());
std::cout << vecs[0]; // Use vecs[0..nVecs-1]
You cannot, however, safely reinterpret the vector itself as a vector of glm::vecX, not even as a const vector, because the number of elements stored in the vector might not be consistent after the reinterpretation. It depends on whether the vector<T> code stores the number of elements directly, or the number of allocated bytes (and then size() divides that by sizeof(T)):
// Don't do this, the result of .size() and .end() may be wrong!
const std::vector<glm::vec3>& bad = *reinterpret_cast<std::vector<glm::vec3>*>(&myObjData);
bad[bad.size()-1].z = 0; // Potential BOOM!
Most of the time, however, you don't need to pass an actual vector, since most functions in the standard library accept a container range, which is easy to give for arrays like the one in the first example. So, if you wanted to sort your vec3 array based on z position, and then print it out you would do:
// nVecs and vecs from the first example
std::sort(vecs, vecs+nVecs, // Sort by Z position
[](const glm::vec3& a, const glm::vec3& b) { return a.z < b.z; });
std::copy(vecs, vecs+nVecs, std::ostream_iterator<glm::vec3>(std::cout, "\n"));
In short: It is - to the best of my knowledge - not possible without copying.
And in my opinion, std::memcpy has no business being used with std::vector.

An object containing a vector referring to another vector's content

My problem is hard to explain, so I'll take the scenario itself as example:
I have a templated Matrix class, which is using a std::vector as storage.
What I'm looking for is having a "row", or "block" method, capable to return another Matrix with a smaller size, but referring to its parent.
With this piece of code:
Matrix<float> mat(2, 2);
// Filling the matrix
Matrix<float> row = mat.row(0); // returns a 1x2 matrix(row vector)
row[1] = 10; // Here I modify the row, which reflects the modifications in mat
std::cout << mat(0, 1); // prints 10
I have been thinking about multiple solutions but all of them have some non-negligible downsides.
Do you have any ideas about how to achieve this?
Thanks!
EDIT 1 :
I forgot to precise, the behavior should be recursive, like getting a block of another block, etc.
Even when implemented correctly, I'd argue that your behavior is counter-intuitive.
Make a seperate MatrixRef class that acts as a reference to a (subset of) a Matrix. This should also make implementation fairly straightforward.

Using Eigen::Map<Eigen::MatrixXd> as function argument of type Eigen::MatrixXd

In short, the question is how to pass a
Eigen::Map<Eigen::MatrixXd>
object to a function which expects a
Eigen::MatrixXd
object.
Longer story:
I have this C++ function declaration
void npMatrix(const Eigen::MatrixXd &data, Eigen::MatrixXd &result);
together with this implementation
void npMatrix(const Eigen::MatrixXd &data, Eigen::MatrixXd &result)
{
//Just do s.th. with arguments
std::cout << data << std::endl;
result(1,1) = -5;
std::cout << result << std::endl;
}
I want to call this function from python using numpy.array as arguments. To this end, I use a wrapper function written in c++
void pyMatrix(const double* p_data, const int dimData[],
double* p_result, const int dimResult[]);
which takes a pointer to data, the size of the data array, a pointer to result, and the size of the result array. The data pointer points to a const patch of memory, since data is not to be altered while the patch of memory reserved for result is writeable. The implementation of the function
void pyMatrix(const double *p_data, const int dimData[], double *p_result, const int dimResult[])
{
Eigen::Map<const Eigen::MatrixXd> dataMap(p_data, dimData[0], dimData[1]);
Eigen::Map<Eigen::MatrixXd> resultMap(p_result, dimResult[0], dimResult[1]);
resultMap(0,0) = 100;
npMatrix(dataMap, resultMap);
}
defines a Eigen::Map for data and result, respectively. A Eigen::Map allows to access raw memory as a kind of Eigen::Matrix. The dataMap is of type
<const Eigen::MatrixXd>
since the associated memory is read only; resultMap in contrast is of type
<Eigen::MatrixXd>
since it must we writeable. The line
resultMap(0,0) = 100;
shows, that resultMap is in deed writeable. While passing dataMap to the npMatrix() where a const Eigen::MatrixXd is expected works, I could not find a way to pass resultMap in the same way. I am sure, the trouble comes from the fact, that the first argument of npMatrix is const, and the second is not. A possible solution I found is to define
Eigen::MatrixXd resultMatrix = resultMap;
and pass this resutlMatrix to npMatrix(). However, I guess, this creates a copy and hence kills the nice memory mapping of Eigen::Map. So my question is.
Is there a way to pass a Eigen:Map to a function which expects a non-const Eigen::MatrixXd instead?
As a side note: I could change npMatrix to expect a Eigen::Map, but since in the real project, functions are already there and tested, I would rather not temper with them.
To complete the question, here is the python file to call pyMatrix()
import ctypes as ct
import numpy as np
import matplotlib.pyplot as plt
# Load libfit and define input types
ct.cdll.LoadLibrary("/home/wmader/Methods/fdmb-refactor/build/pyinterface/libpyfit.so")
libfit = ct.CDLL("libpyfit.so")
libfit.pyMatrix.argtypes = [np.ctypeslib.ndpointer(dtype=np.float64, ndim=2),
np.ctypeslib.ndpointer(dtype=np.int32, ndim=1),
np.ctypeslib.ndpointer(dtype=np.float64, ndim=2, flags='WRITEABLE'),
np.ctypeslib.ndpointer(dtype=np.int32, ndim=1)
]
data = np.array(np.random.randn(10, 2), dtype=np.float64, order='F')
result = np.zeros_like(data, dtype=np.float64, order='F')
libfit.pyMatrix(data, np.array(data.shape, dtype=np.int32),
result, np.array(result.shape, dtype=np.int32))
Pass it as plain pointer to data, and Eigen::Map it there. Alternatively, use template <typename Derived> and the like, found in http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html
My personal Choice is the first though, as it is better to have code that doesn't expose all the stubbornness of every API you have used. Also, you won't lose compatibility neither with eigen ,nor with any other kind of library that you (or anyone else) may use later.
There is also another trick i found out, which can be used in numerous occasions:
Eigen::MatrixXd a;
//lets assume a data pointer like double* DATA that we want to map
//Now we do
new (&a) Eigen::Map<Eigen::Matrix<Double,Eigen::Dynamic,Eigen::Dynamic>> (DATA,DATA rows,DATA cols);
This will do what you ask, without wasting memory. I think it is a cool trick, and a will behave as a matrixXd, but i haven't tested every occasion. It has no memory copy. However, you might need to resize a to the right size before assigning. Even so, the compiler will not immediately allocate all memory at the time you request the resize operation, so there won't be big useless memory allocations either!
Be careful! Resizing operations might reallocate the memory used by an eigen matrix! So, if you ::Map a memory but then you perform an action that resizes the matrix, it might be mapped to a different place in memory.
For anyone still struggling with the problem of passing an Eigen::Map to a function with signature Eigen::Matrix or vice versa, and found the Eigen::Matrix to Eigen::Map implicit casting trick which #Aperture Laboratories suggested didn't work (in my case this gave runtime errors associated with trying to free already released memory, [Mismatched delete / Invalid delete errors when ran with valgrind]),
I suggest using the Eigen::Ref class for function signatures as suggested in the answer given by #ggael here:
Passing Eigen::Map<ArrayXd> to a function expecting ArrayXd&
and written in the documentation:
http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html#TopicUsingRefClass
under the title:
How to write generic, but non-templated function?
For example, for the function specified in the question, changing the signature to
void npMatrix(const Eigen::Ref<const Eigen::MatrixXd> & data, Eigen::Ref< Eigen::MatrixXd> result);
means passing either Eigen::Map<Eigen::MatrixXd> orEigen::MatrixXd objects to the function would work seamlessly (see #ggael's answer to Correct usage of the Eigen::Ref<> class for different ways to use Eigen::Ref in function signature).
I appreciate OP said he didn't want to change the function signatures, but in terms of using Eigen::Maps and Eigen::Matrix's interchangeably I found this the easiest and most robust method.

How to get dimensions of a multidimensional vector in C++

all
I am using multidimensional STL vector to store my data in C++. What I have is a 3D vector
vector<vector<vector<double>>> vec;
What I want to retrieve from it is :
&vec[][1][]; // I need a pointer that points to a 2D matrix located at column 1 in vec
Anyone has any idea to do so? I would be extremly appreciate any help!
Regards
Long
It is best to consider vec just as a vector whose elements happen to be
vectors-of-vectors-of-double, rather than as a multi-dimensional structure.
You probably know, but just in case you don't I'll mention it,
that this datatype does not necessarily represent a rectangular cuboid.
vec will only have that "shape" if you ensure that all the vectors are
the same size at each level. The datatype is quite happy for the vector vec[j]
to be a different size from the one at vec[k] and likewise for vec[j][n]
to be a vector of different size from vec[j][m], so that your structure is "jagged".
So you want to get a pointer to the vector<vector<double>> that is at
index 1 in vec. You can do that by:
vector<vector<double>> * pmatrix = &vec[1];
However this pointer will be an unnecessarily awkward means of accessing that
vector<vector<double>>. You certainly won't be able to write the
like of:
double d = pmatrix[j][k];
and expect to get a double at coordinates (j,k) in the "matrix addressed
by a pmatrix". Because pmatrix is a pointer-to-a-vector-of-vector-of-double;
so what pmatrix[j] refers to is the vector-of-vector-of-double (not vector-of-double)
at index j from pmatrix, where the index goes in steps of
sizeof(vector<vector<double>>). The statement will reference who-knows-what
memory and very likely crash your program.
Instead, you must write the like of:
double d = (*pmatrix)[j][k];
where (*pmatrix) gives you the vector-of-vector-of-double addressed by pmatrix,
or equivalently but more confusingly:
double d = pmatrix[0][j][k];
Much simpler - and therefore, the natural C++ way - is to take a reference,
rather than pointer, to the vector<vector<double>> at index 1 in vec. You
do that simply by:
vector<vector<double>> & matrix = vec[1];
Now matrix is simply another name for the vector<vector<double>> at index 1 in vec,
and you can handle it matrix-wise just as you'd expect (always assuming
you have made sure it is a matrix, and not a jagged array).
Another thing to consider was raised in a comment by manu343726. Do you
want the code that receives this reference to vec[1] to be able to
use it to modify the contents of vec[1] - which would include changing its
size or the size of any of the vector<double>s within it?
If you allow modification, that's fine. If you don't then you want to get
a const reference. You can do that by:
vector<vector<double> > const & matrix = vec[1];
Possibly, you want the receiving code to be able to modify the doubles
but not the sizes of the vectors that contain them? In that case, std::vector
is the wrong container type for your application. If that's your position I
can update this answer to offer alternative containers.
Consider using matrix from some linear algebra library. There are some directions here