Suppose I have a very large array of data:
double matrix[100000][100] = {0.0};
During runtime this data is updated. Now I want to give the reference to this data to a function FUNC. However, I want to only give one column to the function FUNC, like:
FUNC(matrix["all elements"]["only column with index 5"]);
and not the entire array. Furthermore, I dont want to perform a copy operation before (because this is slow), I just want to give the pointer or reference to the specific rows/columns inside the large array data. The function should only see an array like:
void FUNC(double* array)
{
for (int i = 0; i < 100000; i++)
doSomething(array[i]);
}
How do I do give this partial data from array "matrix" to the function FUNC?
The column values of your matrix are not sequential in memory, so you can't pass a single column to FUNC() without making a copy of the data into a sequential array. However, if you are able to add the column index as an additional parameter to FUNC() then you can do something like this instead:
const int MAX_ROWS = ...;
const int MAX_COLS = ...;
using Matrix = double[MAX_ROWS][MAX_COLS];
void doSomething(double value)
{
...
}
void FUNC(const Matrix& matrix, int column)
{
for (int row = 0; row < MAX_ROWS; ++row) {
doSomething(matrix[row][column]);
}
}
Matrix matrix = {};
...
FUNC(matrix, 5);
Online Demo
Related
I am trying to create an array of X pointers referencing matrices of dimensions Y by 16. Is there any way to accomplish this in C++ without the use of triple pointers?
Edit: Adding some context for the problem.
There are a number of geometries on the screen, each with a transform that has been flattened to a 1x16 array. Each snapshot represents the transforms for each of number of components. So the matrix dimensions are 16 by num_components by num_snapshots , where the latter two dimensions are known at run-time. In the end, we have many geometries with motion applied.
I'm creating a function that takes a triple pointer argument, though I cannot use triple pointers in my situation. What other ways can I pass this data (possibly via multiple arguments)? Worst case, I thought about flattening this entire 3D matrix to an array, though it seems like a sloppy thing to do. Any better suggestions?
What I have now:
function(..., double ***snapshot_transforms, ...)
What I want to accomplish:
function (..., <1+ non-triple pointer parameters>, ...)
Below isn't the function I'm creating that takes the triple pointer, but shows what the data is all about.
static double ***snapshot_transforms_function (int num_snapshots, int num_geometries)
{
double component_transform[16];
double ***snapshot_transforms = new double**[num_snapshots];
for (int i = 0; i < num_snapshots; i++)
{
snapshot_transforms[i] = new double*[num_geometries];
for (int j = 0; j < num_geometries; j++)
{
snapshot_transforms[i][j] = new double[16];
// 4x4 transform put into a 1x16 array with dummy values for each component for each snapshot
for (int k = 0; k < 16; k++)
snapshot_transforms[i][j][k] = k;
}
}
return snapshot_transforms;
}
Edit2: I cannot create new classes, nor use C++ features like std, as the exposed function prototype in the header file is getting put into a wrapper (that doesn't know how to interpret triple pointers) for translation to other languages.
Edit3: After everyone's input in the comments, I think going with a flattened array is probably the best solution. I was hoping there would be some way to split this triple pointer and organize this complex data across multiple data pieces neatly using simple data types including single pointers. Though I don't think there is a pretty way of doing this given my caveats here. I appreciate everyone's help =)
It is easier, better, and less error prone to use an std::vector. You are using C++ and not C after all. I replaced all of the C-style array pointers with vectors. The typedef doublecube makes it so that you don't have to type vector<vector<vector<double>>> over and over again. Other than that the code basically stays the same as what you had.
If you don't actually need dummy values I would remove that innermost k loop completely. reserve will reserve the memory space that you need for the real data.
#include <vector>
using std::vector; // so we can just call it "vector"
typedef vector<vector<vector<double>>> doublecube;
static doublecube snapshot_transforms_function (int num_snapshots, int num_geometries)
{
// I deleted component_transform. It was never used
doublecube snapshot_transforms;
snapshot_transforms.reserve(num_snapshots);
for (int i = 0; i < num_snapshots; i++)
{
snapshot_transforms.at(i).reserve(num_geometries);
for (int j = 0; j < num_geometries; j++)
{
snapshot_transforms.at(i).at(j).reserve(16);
// 4x4 transform put into a 1x16 array with dummy values for each component for each snapshot
for (int k = 0; k < 16; k++)
snapshot_transforms.at(i).at(j).at(k) = k;
}
}
return snapshot_transforms;
}
Adding a little bit of object-orientation usually makes the code easier to manage -- for example, here's some code that creates an array of 100 Matrix objects with varying numbers of rows per Matrix. (You could vary the number of columns in each Matrix too if you wanted to, but I left them at 16):
#include <vector>
#include <memory> // for shared_ptr (not strictly necessary, but used in main() to avoid unnecessarily copying of Matrix objects)
/** Represents a (numRows x numCols) 2D matrix of doubles */
class Matrix
{
public:
// constructor
Matrix(int numRows = 0, int numCols = 0)
: _numRows(numRows)
, _numCols(numCols)
{
_values.resize(_numRows*_numCols);
std::fill(_values.begin(), _values.end(), 0.0f);
}
// copy constructor
Matrix(const Matrix & rhs)
: _numRows(rhs._numRows)
, _numCols(rhs._numCols)
{
_values.resize(_numRows*_numCols);
std::fill(_values.begin(), _values.end(), 0.0f);
}
/** Returns the value at (row/col) */
double get(int row, int col) const {return _values[(row*_numCols)+col];}
/** Sets the value at (row/col) to the specified value */
double set(int row, int col, double val) {return _values[(row*_numCols)+col] = val;}
/** Assignment operator */
Matrix & operator = (const Matrix & rhs)
{
_numRows = rhs._numRows;
_numCols = rhs._numCols;
_values = rhs._values;
return *this;
}
private:
int _numRows;
int _numCols;
std::vector<double> _values;
};
int main(int, char **)
{
const int numCols = 16;
std::vector< std::shared_ptr<Matrix> > matrixList;
for (int i=0; i<100; i++) matrixList.push_back(std::make_shared<Matrix>(i, numCols));
return 0;
}
So we want to approximate the matrix A with m rows and n columns with the product of two matrices P and Q that have dimension mxk and kxn respectively. Here is an implementation of the multiplicative update rule due to Lee in C++ using the Eigen library.
void multiplicative_update()
{
Q = Q.cwiseProduct((P.transpose()*matrix).cwiseQuotient(P.transpose()*P*Q));
P = P.cwiseProduct((matrix*Q.transpose()).cwiseQuotient(P*Q*Q.transpose()));
}
where P, Q, and the matrix (matrix = A) are global variables in the class mat_fac. Thus I train them using the following method,
void train_2(){
double error_trial = 0;
for (int count = 0;count < num_iterations; count ++)
{
multiplicative_update();
error_trial = (matrix-P*Q).squaredNorm();
if (error_trial < 0.001)
{
break;
}
}
}
where num_iterations is also a global variable in the class mat_fac.
The problem is that I am working with very large matrices and in particular I do not have access to the entire matrix. Given a triple (i,j,matrix[i][j]), I have access to the row vector P[i][:] and the column vector Q[:][j]. So my goal is to write rewrite the multiplicative update rule in such a way that I update these two vectors every time, I see a non-zero matrix value.
In code, I want to have something like this:
void multiplicative_update(int i, int j, double mat_value)
{
Eigen::MatrixXd q_vect = get_vector(1, j); // get_vector returns Q[:][j] as a column vector
Eigen::MatrixXd p_vect = get_vector(0, i); // get_vector returns P[i][:] as a column vector
// Somehow compute coeff_AQ_t, coeff_PQQ_t, coeff_P_tA and coeff_P_tA.
for(int i = 0; i< k; i++):
p_vect[i] = p_vect[i]* (coeff_AQ_t)/(coeff_PQQ_t)
q_vect[i] = q_vect[i]* (coeff_P_tA)/(coeff_P_tA)
}
Thus the problem boils down to computing the required coefficients given the two vectors. Is this a possible thing to do? If not, what more data do I need for the multiplicative update to work in this manner?
So I'm very new to c++, studying it at present and have a piece of work to do that's stumping me. You guys are the first port of call.
I need to make what is essentially a 2d array of objects. The header file includes Cell objects for rows, columns and blocks. The idea that I have a 9x9 array of objects, with relevant pointers based on column, row and internal 3x3 block therein. What I'm stuck on is that the below line fills out the 9x9 but how am I pointing to each Cell?
Or is that in something separate and this is all I need to do for just setting up that grid??
void SudokuPuzzle::InitialiseGrid()
{
for (int row = 0; row < 9; row++)
{
for (int column = 0; column < 9; column++)
{
m_gridRows[row].SetCell(column, new SudokuSquare());
// have the cell point to both it's position in the column and block
}
}
}
Maybe try to create the 2d array of the Type "SudokuSquare".
SudokuSquare sSquare [9][9];
So you can acces any object by
sSquare[row][column];
If your array is fixed size e.g. 3x3 just use std::array:
#include <array>
using std::array;
int main()
{
array<array<int, 3>, 3> sudoku_squares{};
sudoku_squares[0][1] = 1; // sets cell at first row, second column to 1
return 0;
}
In your case you can store 9 of those 3x3 arrays in another array or just use 9x9 array and you don't need to use any pointers. I used int in my example but you can store SudokuSquare exactly the same way.
In a small application, I've been using a std::vector of std::vector<std::string> to temporarily store
some data (pulled from a non-SQL database) before processing it and uploading it to a SQL database. Unfortunately,
the API from which I am extracting the data does not necessarily return fields in the order specified by a query;
e.g. if my query requests fields x, y, z, the data may be returned as y, x, z, or z, y, x, etc... Obviously
this is problematic because if the target SQL table's columns are x, y, z, then the data being inserted needs
to reflect this.
To account for this random field ordering, I wrote a small function that takes (1) the input data, as returned by the API;
and (2) a std::vector<std::string> representing the desired column ordering, as defined in the SQL table - and
reorders the elements of each subvector accordingly. Since the first row of the input data is a vector of field
names, I'm able to compare it to the correctly ordered vector and determine how each subvector should be
reordered:
void fix_order(std::vector<std::vector<std::string>>& data, const std::vector<std::string>& correct) {
std::size_t width = data[0].size();
std::vector<int> order_idx(width);
for (std::size_t i = 0; i < width; i++) {
std::string tmp(data[0].at(i));
auto pos = std::find(correct.begin(), correct.end(), tmp);
order_idx[i] = std::distance(correct.begin(), pos);
}
for (std::size_t i = 0; i < data.size(); i++) {
if (!data[i].empty()) {
std::vector<std::string> q(width);
for (unsigned int j = 0; j < width; j++) {
int new_pos = order_idx[j];
q[new_pos] = data[i].at(j);
}
std::swap(data[i], q);
}
}
}
In action, if the input data fields were ordered as second, fourth, first, third, and I passed a vector specifying the correct order as first, second, third, fourth, the transformation looks like this:
Before:
second fourth first third
2nd 4th 1st 3rd
2nd 4th 1st 3rd
After:
first second third fourth
1st 2nd 3rd 4th
1st 2nd 3rd 4th
Although the function produces the desired result, my mixture of loops and STL algorithms feels sloppy and just not very readable in general. In other situations I've typically been able to use std::sort with a custom comparator function for nonstandard sorting, but I was not able to figure out how to adapt this approach here, where the "sorting" is determined by a predefined input, rather than some type of comparison-based logic. Is there a more idiomatic way to accomplish this - i.e. making better use of STL algorithms (not necessarily std::sort) or other C++ idioms?
Here's an online demo to reproduce the situation.
If you transpose the data, it's as easy as sorting the vectors by the index of the first element in them. This will be slower than your solution but may be more readable:
void fix_order(std::vector<std::vector<std::string>>& data, const std::vector<std::string>& correct) {
// setup index map, e.g. "first" --> 0
std::unordered_map<std::string, size_t> idx;
for (size_t i = 0; i < correct.size(); ++i) {
idx.insert(std::make_pair(correct[i], i));
}
// transpose for efficient sorting
auto tp = transpose(std::move(data));
// sort based on index map
std::sort(tp.begin(), tp.end(), [&](const std::vector<std::string>& lhs, const std::vector<std::string>& rhs){
return idx[lhs[0]] < idx[rhs[0]];
});
// transpose back to get the form you wanted
data = transpose(std::move(tp));
}
Where transpose is just:
std::vector<std::vector<std::string>> transpose(std::vector<std::vector<std::string>>&& data)
{
std::vector<std::vector<std::string>> result(data[0].size(),
std::vector<std::string>(data.size()));
for (size_t i = 0; i < data[0].size(); ++i) {
for (size_t j = 0; j < data.size(); ++j) {
result[i][j] = std::move(data[j][i]);
}
}
return result;
}
I'm pretty new to C++ and got an assignment to make a matrix using only STL containers. I've used a vector (rows) of vectors (columns). The problem I'm having is in the 'write' operation - for which I may only use an iterator-based implementation. Problem is, quite simply: it writes nothing.
I've tested with a matrix filled with different values, and while the iterator ends up on exactly the right spot, it doesn't change the value.
Here's my code:
void write(matrix mat, int row, int col, int input)
{
assert(row>=0 && col>=0);
assert(row<=mat.R && col<=mat.C);
//I set up the iterators.
vector<vector<int> >::iterator rowit;
vector<int>::iterator colit;
rowit = mat.rows.begin();
//I go to the row.
for(int i = 0; i<row-1; ++i)
{
++rowit;
}
colit = rowit->begin();
//I go to the column.
for(int j = 0; j<col-1; ++j)
{
++colit;
}
*colit = input; //Does nothing.
}
What am I overlooking?
Thanks.
matrix mat is a parameter by value, it copies the matrix and hence you are writing to a copy.
You should pass the matrix by reference instead, like matrix & mat.
But wait... You are passing the matrix every time as the first parameter, this is a bad sign!
This usually indicates that the parameter should be turned into an object on which you can run the methods; that way, you don't need to pass the parameter at all. So, create a Matrix class instead.
Please note that there is std::vector::operator[].
So, you could just do it like this:
void write(matrix & mat, int row, int col, int input)
{
assert(row>=0 && col>=0);
assert(row<=mat.R && col<=mat.C);
mat[row][col] = input;
}