In my PhD, I very often use matrices of various dimensions and data types. For first time, I use recursive templates in C++11 for manipulating my non-contagious arrays, so it is the last time I see calloc
and free
. With the help of stackoverflow link1 and link2 I achieved my initial goal of de&allocating them. Greedy me, I now want my class to perform the basic cellwise operations e.i. addition, division. It works fine if I use enum
to determine which operation is performed, but I fail to use reference to an other templated function that performs the operation. The enum
way:
The main:
//Define the size of each dimension in a vector
int height = 3, width = 2;
std::vector<int> dimensions;
dimensions.push_back(height);
dimensions.push_back(width);
// Allocate a table of doubles 3x2
smatrix<double **> dbltbl(dimensions);
// Assign values in the cells
for (int r = 0; r < height; ++r)
for (int c = 0; c < width; ++c) {
dbltbl.uacc()[r][c] = (double)(r * width + c) * 2.6;
}
// Create a table of ints from the table of doubles (rounded copy)
smatrix<int **> inttbl = dbltbl;
// Add cell-wise the table of ints to the table of doubles
dbltbl.cellwise_add(inttbl);
The enum
:
enum clc_op { addition, subtration, multiplication, division };
The operation function:
template <typename S, typename T>
T add(S one, T two) {
return (T)one + two;
}
The recursive template solution:
template <typename S, typename T>
void cellwise_ops(S &src, T &dest, std::vector<int> dims, enum clc_op operation) {
switch (operation) {
case clc_op::addition:
dest = add(src, dest);
break;
//…
//...
}
}
template <typename S, typename T>
void cellwise_ops(S *src, T *dest, std::vector<int> dims, enum clc_op operation) {
if (dims.size() == 0)
return false;
int toimp = dims.front();
dims.erase(dims.begin());
for (int i = 0; i < toimp; ++i) {
cellwise_ops(src[i], dest[i], dims, operation)
}
}
The class method (e.g. P = double** and U=int**):
template <typename P>
template <typename U>
void smatrix<P>::cellwise_add(smatrix<U> const &addend) {
U temp = addend.uacc();
cellwise_ops(temp, _full, _dim, clc_op::addition);
}
The output:
==========================================
Table of doubles:
0 2.6
5.2 7.8
10.4 13
==========================================
Table of ints from the table of doubles:
0 2
5 7
10 13
==========================================
Table of doubles+ints:
0 4.6
10.2 14.8
20.4 26
This solution doesn’t look elegant, making me believe it is the wrong approach. So, I try to pass the operation as reference to function, and I fail hard time:
The addition (operation) function remains the same. The recursive solution:
template <typename S, typename T>
void cellwise_ops(S &src, T &dest, std::vector<int> dims, T (*operation)(S, T)) {
dest = operation(src, dest);
}
template <typename S, typename T>
void cellwise_ops(S *src, T *dest, std::vector<int> dims, T (*operation)(S, T)) {
if (dims.size() == 0)
return false;
int toimp = dims.front();
dims.erase(dims.begin());
for (int i = 0; i < toimp; ++i) {
cellwise_ops(src[i], dest[i], dims, operation);
}
}
The class method:
template <typename P>
template <typename U>
void smatrix<P>::cellwise_add(smatrix<U> const &addend) {
U temp = addend.uacc();
cellwise_ops(temp, _full, _dim, add<U, P>);
}
The error:
./sm_example/smatrix.hpp:305:17: required from ‘void smatrix<P>::cellwise_add(const smatrix<U>&) [with U = int**; P = double**]’
./sm_example/sm_example.cpp:157:35: required from here
./sm_example/smatrix.hpp:159:19: error: invalid operands of types ‘double**’ and ‘double**’ to binary ‘operator+’
return (T)one + two;
I understand that addition between pointers is not allowed, although I know it will not happen the compiler doesn't. I have no clue how I could work around it. How do I pass the operation’s template-function (add
) by reference in the recursive template-function? Do I use templates in a wrong way?
I do not want to use std::vector
for the time being, but comments are welcome. Worst case scenario, my dataset reaches 100MBytes in 5 dimensions.
If you made it so far, thank you! Chris
Aucun commentaire:
Enregistrer un commentaire