I would like to matrix multiply data in std::mdspan i.e. have something like
auto mat_mult(std::mdspan, std::mdspan) -> mdvector;
But as far as I can tell Eigen only supports owning MatrixXd
To be as confusing as possible, Eigen calls its non-owning type Map
float data[] = {1,2,3,4};
Map<Vector3f> v1(data); // uses v1 as a Vector3f object
Map<ArrayXf> v2(data,3); // uses v2 as a ArrayXf object
Map<Array22f> m1(data); // uses m1 as a Array22f object
Map<MatrixXf> m2(data,2,2); // uses m2 as a MatrixXf object
https://eigen.tuxfamily.org/dox/group__QuickRefPage.html
Related
The C function :
void foo(int* p){
*p = 10;
}
And js call :
var a = 0;
foo(a);
console.log(a);//expect a to be 10
There is no way to have out-parameters for primitive types in JavaScript, and V8's API tries pretty hard not to create behaviors that are inconsistent with JavaScript, because that would be weird™.
An alternative solution is to embed the field in an object:
var a = {value: 0}
foo(a);
console.log(a.value); // This can be made to print 10.
With that approach, you can use the normal way of binding functions via V8's API, and on the C++ side simply modify the respective property of the object that was passed in.
Back in '98 I converted my chemical model from objective-c to c++ after replacing my old NeXT, but I didn't really get a chance to learn c++. I'm now rewriting the code into modern c++, which means learning to use containers, smart pointers, and templates.
I need to parse output variables only once up front, rather than at each time step, so I originally produced a pointer array of output variable pointers (float ***outVars). I could run through the list of pointers after each time interval, and since outVars pointed to the original data, they would always provide the current state of the model.
I'm changing code from matrices of naked pointers to matrices of vectors. I haven't been able to return anything but copies of vectors, rather than references to the original vectors. I don't want to modify the vectors, I just need direct read access.
I can't believe I haven't found my answer online yet. Most that I've found online has simply said use std::vector<float> & to return by reference, but clearly that isn't working.
I saw one note that assigning a reference to a non-reference value (I assume they meant variable) will make it copy, so I tried fvec2D &outVar2D; (see the header file below).
I've tried with and without const, no difference.
I've tried returning vector.data(), but assigning it to a new vector was also copying. Maintaining pointers to .data() memory blocks seems be a very bad idea, if I need to resize the original vector.
I've tried wrapping the vector in std::shared_ptr, but found I'd need to wrap each dimension vector in a shared_ptr, which got overly cumbersome real fast.
I saw one suggestion to return vector::iterators. I haven't managed to get that to work yet. Maybe having 2D data is getting in the way of that. I'm still trying to get that to run without crashing when I examine the iterator.
I don't know if using a 1D array would solve this, but calculating every index reference for millions of calls seems suboptimal.
I considered using std::array too but vectors seemed the simplest conversion. Perhaps I should rethink that.
If anyone has any suggestions for how to do this, I'd very much appreciate it.
class chem - manages original matrix concentration
class chem
{
public:
typedef std::vector<float> fvec1D;
typedef std::vector<std::vector<float> > fvec2D;
chem(int xstep, int zstep) : concentration(xstep, fvec1D(zstep, 1.5)) {}
...
const fvec2D &getConc() const { return concentration; }
const fvec1D &getConc(int x) const {return concentration[x]; }
private:
fvec2D concentration;
};
class model - needs read access to chem::concentration
class model
{
public:
typedef std::vector<float> fvec1D;
typedef std::vector<std::vector<float> > fvec2D;
...
private:
fvec2D null2D {{0.0}};
fvec1D null1D {0.0};
fvec2D &outVar2D;// = null2D; // tried this and at ctor
fvec1D &outVar1D;// = null1D;
std::vector<std::unique_ptr<chem> > chemList;
};
model::model() : outVar2D(null2D), outVar1D(null1D)
{
outVar2D = chemList[0]->getConc(); // or
outVar1D = chemList[0]->getConc(1);
}
void model::plot()
{
for (int z=0; z<numZSteps; ++z) {
std::cout << outVar1D[z];
std::cout << outVar2D[1][z];
}
}
void model::run()
{
plot(); // produces init concentration of 1.5 at each z
chemList[0]->changeConc(); // Changes values in concentration
plot(); // STILL produces init conc of 1.5 at each z
}
I don't know if answering my own question is appropriate (please let me know). I know this question will be autodeleted, so I thought I'd present the solution I came up with, because I'm still VERY interested in hearing any suggestions of the best way to do this. I'm still so far down the learning curve I know I can't intuitively see c++ programming techniques.
I gathered from comments that what I was trying won't work, so I wrapped my vectors in shared_ptrs, which I know can work. I created some wrapper classes to manage 2 levels of shared_ptr (one for the multidimensional spatial data, and one for the list of output variables). It also keeps the array-type indexing intact as well as defines behavior for operator=.
I have only included the 2D classes here. I have 4 similar classes to handle the 1D and 3D cases as well.
I know what I'm posting is not great. it's not very elegant, requiring 2 classes for each dimensional case (1D, 2D, 3D data). Perhaps I can simplify it using templates. I've only written very elementary templates so far. Since each class decays (using operator[]) to a unique class I'm not sure if a template will help.
I haven't figured out all the const keyword placements yet - I removed them all for now, out of frustration with the compiler complaints. I'll get that down when I can take the time.
I also don't know exactly what sort of behavior I want for copy and move constructors, though I'm pretty sure I need them for vector resize operations, which I just realized I haven't even implemented yet. The important thing for me here was just to get read access to the vectors across classes, such that when the vectors change it is reflected elsewhere without re-parsing my output variables.
#include <memory>
#include <vector>
namespace MDType {
class fpv2D;
typedef std::vector<float> fvec1D;
typedef std::vector<std::vector<float> > fvec2D;
typedef std::vector<std::vector<std::vector<float> > > fvec3D;
typedef std::shared_ptr<fvec1D> fvec1Dptr;
typedef std::shared_ptr<fvec2D> fvec2Dptr;
typedef std::shared_ptr<fvec3D> fvec3Dptr;
typedef std::vector<fpv2D> fvpv2D;
typedef std::shared_ptr<fvpv2D> fvpv2Dptr;
class fpv2D
{
public:
fpv2D(int x=1, int z=1, float fill=0.0) : theArray(new fvec2D(x, fvec1D(z, fill))) {}
fpv2D(const fpv2D &otherT) = default; // Pretty sure this needs to change
fpv2D( fpv2D &&otherT) {theArray = otherT.data(); }
fvec2Dptr &data() { return theArray; }
fvec1D &operator[](int index) {return theArray->data()[index]; }
void operator=( fpv2D& rhs) { theArray = rhs.data(); }
private:
fvec2Dptr theArray;
};
class fpvpv2D
{
public:
fpvpv2D(int index, int x=1, int z=1, float fill=0.0) : theArray(new fvpv2D(index, fpv2D(x, z, fill))) {}
fpvpv2D(const fpvpv2D &otherT) = default; // Pretty sure this needs to change
fpvpv2D( fpvpv2D &&otherT) {theArray = otherT.data(); }
fvpv2Dptr &data() { return theArray; }
fpv2D &operator[](int index) {return theArray->data()[index]; }
void operator=( fpvpv2D& rhs) { theArray = rhs.data(); }
private:
fvpv2Dptr theArray;
};
}
... so ...
MDType::fpv2D conc(numX, numZ, 1.5);
MDType::fpvpv2D outVar2D(numOutVars, numX, numZ);
outVar2D[1] = conc;
cout << outVar2D[1][3][5]; // prints 1.5
conc[3][5] = 12.0;
cout << outVar2D[1][3][5]; // prints 12.0
Every now and then I come across a situation when I need to create an array of non-copy-constructible objects. For example:
std::vector<std::thread> thread_pool(NUM_CORES, std::thread(some_function));
That would be convenient. But alas, the std::vector fill constructor doesn't seem to have any support for R-values. It is defined as:
vector(
size_type count,
const T& value,
const Allocator& alloc = Allocator()
);
But it would be extremely convenient to have:
vector(
size_type count,
T&& value,
const Allocator& alloc = Allocator()
);
Then the vector could internally allocate the necessary buffer size, and move-construct each element with placement new.
But... the C++11 standard (and apparently even the C++14 standard) don't provide this capability. So, now - when I have a vector of threads, I have to say:
std::vector<std::unique_ptr<std::thread>> thread_pool(NUM_CORES);
/* now loop over vector and initialize elements one by one */
Is there some reason this ability was left out? Is there some danger? Or some problem that I'm not seeing?
What you propose is not feasible because, by its very nature, moving is the transfer of a state from one object to one other object. You cannot construct N objects by moving state from one to all of them at the same time.
The Stargate universe violated this rule by introducing the ability to open a wormhole to every gate in the galaxy simultaneously, which made no sense at all and really annoyed me. Don't be that guy!
A vector constructor looking like this:
template <typename T>
template <typename Args...>
std::vector<T>::vector(const size_t n, Args&&... args);
…following the emplace model could work, though I worry that it would be easy to get an ambiguous overload thanks to the sheer number of existing constructors for std::vector<T>. I suspect this is why it was not done, besides the fact that it isn't really necessary.
Because, for now, you can workaround it by emplacing one at a time which, regardless, is probably as performant as you can ever hope to get:
std::vector<std::thread> v;
v.reserve(NUM_CORES);
for ( /*...*/ )
v.emplace_back( /*...*/ );
I have:
Eigen::MatrixXf load_from_gpu()
{
Eigen::MatrixXf mat(m_rows,m_cols);
clEnqueueReadBuffer(m_manager->m_gpu_queue_loader, m_buffer, CL_TRUE, 0, sizeof(float)*numel(), mat.data(), 0, NULL, NULL);
return mat;
}
I belive that when i call this method the data is stored to one mat and then copyed to mat2 : Eigen::MatrixXf mat2 = load_from_gpu();
Is it possible to make it write the data into the matrix which is the rhs of the function call of load_from_gpu()
Your compiler should be able to do this for you, using the common Return Value Optimization method. Basically what this does, is that the compiler rewrites load_from_gpu to take a pointer to an Eigen::MatrixXf as a parameter, and fill that matrix directly.
Note that it can only do this because it can see that mat will always be the return value, if there are several matrices in the methods and one gets returned based on some condition, the compiler doesn't know which one to replace with the hidden pointer parameter. In this case you have to resort to doing it manually, like in alrikai's answer.
To enable the optimization you have to compile with -O2 with GCC.
I haven't used Eigen much, but can't you pass your Matrix as a reference parameter and assign it in load_from_gpu()? That is,
void load_from_gpu(Eigen::MatrixXf& mat)
{
clEnqueueReadBuffer(m_manager->m_gpu_queue_loader, m_buffer, CL_TRUE, 0, sizeof(float)*numel(), mat.data(), 0, NULL, NULL);
}
I have a class which inherits QAbstractTableModel, and holds some complex structs in a QMap. The QVariant data(QModelIndex index, ...) method just returns an enum which describes how a custom item delegate should draw the contents of a cell. I would like to implement drag and drop functionality in this model so that users can reorder these structs in the QMap, but can't quite figure our how Qt would like me to do this. All I need is to see the source and destination indices of the drag/drop operation and I can take care of the rest, but the closest thing I've found in QAbstractItemModel is the dropMimeData() function. DropMimeData() doesn't give me the source index and requires me to convert the data into some MIME type (plaintext, etc.), which it is definitely not. I can hack my way through this by creating a QMimeData that just contains the source index, but I would like to really learn to use Qt as it's meant to be used, and I feel like I'm missing something. Any thoughts?
Just to help clarify a bit, the application is an animation program which acts sort of like Adobe Flash. The class which inherits QAbstractTableModel has a QMap<int, FrameState> (with struct FrameState{QPointF pos; bool visible;}) to hold keyframes. This state of this QMap is what I would like to display and have users edit. I draw a green circle if there is a visible key frame, a red circle if there is an invisible keyframe, a line if the previous keyframe was visible, and nothing if the previous keyframe was invisible. I would like users to be able to drag the keyframes around to change their QMap key.
Thanks!
You can use the views dragEnterEvent to get the indices that were selected initially:
void DropTreeView::dragEnterEvent(QDragEnterEvent *event)
{
QTreeView::dragEnterEvent(event);
const QItemSelectionModel * sm = selectionModel();
if (!sm)
return;
dragStartIndicies = sm->selectedIndexes();
}
You'll need to use the mime-types for the drag and drop, but C++ Qt provides a nice way to do that using QDataStream:
QMimeData *YourModel::mimeData( const QModelIndexList &indexes ) const
{
QByteArray encodedData;
QDataStream stream( &encodedData, QIODevice::WriteOnly );
stream << yourQMap /* OR almost any Qt data structure */;
QMimeData *mData = new QMimeData();
mData->setData( YOUR_MIME_TYPE, encodedData );
return mData;
}
On the receiving end, you can get your data structure (i.e. QMap if that's what you want to use) back out of the QDataStream:
QByteArray encodedData = yourMimeData->data( YOUR_MIME_TYPE );
QDataStream stream( &encodedData, QIODevice::ReadOnly );
QMap decodedMap;
stream >> decodedMap;