Using less matrices with BLAS - c++

I'm quite new to BLAS (using OpenBLAS with C++ and VisualStudio)
I know dgemm performs C <- alpha * op(A) * op(B) + beta * C
I was trying to save some allocation doing this: B <- 1 * op(A) * op(B) + 0 * B
In other words, putting the result in the B matrix,
BUT making beta = 0 and repeating B in the position of C, results in a zero answer.
Is there a way to make it right?
The code that I'm using:
double* A = new double [3*3]; //3 rows x 3 columns
A[0] = 8;
A[1] = 3;
A[2] = 4;
A[3] = 1;
A[4] = 5;
A[5] = 9;
A[6] = 6;
A[7] = 7;
A[8] = 2;
double* v = new double[3]; //3 rows x 1 column
v[0] = 3;
v[1] = 5;
v[2] = 2;
double* foo = new double[3]; //3 rows x 1 column
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans,
3, 1, 3,
1,
A, 3,
v, 3,
0,
foo, 3); // makes foo = [41 ; 48 ; 61], **right**
cblas_dgemm(CblasColMajor, CblasTrans, CblasTrans,
3, 1, 3,
1,
A, 3,
v, 3,
0,
v, 3); // makes v = [0 ; 0 ; 0], **wrong**

BLAS dgemm function documentation states that only the C matrix parameter is for both input and output, being overwritten by the operation result. As B is defined just for input, BLAS implementations can assume that it shouldn't be modified.
Setting B and C to the same data pointer could be triggering some error verification on the implementation you're using, returning the zeroed result to indicate that.

Related

Transfer a matrix into an array

I was solving a problem that asked me to operate a double subscripted array by using a single-subscripted array. Hence, the question is: how can a double-subscripted array be transformed into a single-subscripted array? or if it can't be transformed.. How can you operate a double-subscripted through a single-subscripted array?
For example:
int matrix[ m ][ n ];
//How can you transform matrix into array? Or operate it?
int array[ m * n ];
Basically, the problem asks this: "Create a class DoubleSubscriptedArray. At construction time, the class should be able to create an array of any number of rows and any number of columns.The underlying representation of the double-subscripted array should be a single-subscripted array of integers with rows * columns number of elements"
Your matrix is stored as m times n elements contiguously in memory. What you can do is interpret the first element of your matrix as a int*, and you have your array. It prevents copying the elements.
int main()
{
int matrix[3][3] = { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} };
int* array = &matrix[0][0];
// int array[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1}
return 0;
}
If you need to copy your elements, you can try
#include <memory>
int main()
{
int matrix[3][3] = { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} };
int array[9];
std::memcpy(&array[0], &matrix[0][0], sizeof(array));
// int array[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1}
return 0;
}
The simplest answer:
int array[m * n];
for (int y = 0; y < n; ++y) {
for (int x = 0; x < m; ++x) {
array[y * m + x] = matrix[x][y];
}
}
Where:
y - row number
x - column number
Now you need to serialize all rows into one:
row_no/col_no | 0 | 1 | 2 |
______________|___|___|___|
0 | 1 | 2 | 3 | <-- matrix data
1 | 4 | 5 | 6 |
||
\ /
\/
array_no 0 1 2 3 4 5
| | | | | |
[ 1, 2, 3, 4, 5, 6 ] <-- array data
array_no = row_no * number_of_rows + col_no
You can TEST it :)
P.S You can also do it like this:
int* array = (int*)matrix;
It is version without copying :)
You can recalculate index of one dimension array to store the coresponding value of two dimensional array.
If you need to copy, eficient approuch would be to copy raw by row from two dim array to one dim, cause multidimensional arrays are stored in raw mayor order,
and index can be calculated as
oneDimIndex = row*n+col
where you are fetching element at matrix[row,col]
And after, you can retrieve content from one dimension array with same calculation.

Eigen matrix rowwise addition

I have an Nx3 Eigen matrix representing a bunch of locations of vertices in 3d space.
I'm trying to add a 1x3 matrix to each row in the Nx3 to move every point a given direction and distance.
#include <Eigen/Dense>
int N = 20; //for example
MatrixXf N3(N, 3);
N3.fill(2);
MatrixXf origin(1, 3);
origin << 1, 2, 3;
Now I want to add origin to each row in N3 so N3 becomes 3, 4, 5 in each row. (The values in N3 are all different 3d vertex locations in the real code.)
3, 4, 5
3, 4, 5
3, 4, 5 etc...
you may just write
N3 += origin.replicate(N,1);
note that no temporary matrix is created, replicate() returns an expression.
Try this (untested)
for (int i = 0 ; i < 3 ; i++)
N3.block(i, 0, 1, 3) = N3.block(i, 0, 1, 3) + origin
I do not remember if += is supported
MatrixXf result = N3 + MatrixXf::Constant(1, N, 1) * origin;
Should be simple as that.

Multiplication of each matrix column by each vector element using Eigen C++ Library

I need to multiply each matrix column by each vector element using Eigen C++ library. I tried colwise without success.
Sample data:
Eigen::Matrix3Xf A(3,2); //3x2
A << 1 2,
2 2,
3 5;
Eigen::Vector3f V = Eigen::Vector3f(2, 3);
//Expected result
C = A.colwise()*V;
//C
//2 6,
//4 6,
//6 15
//this means C 1st col by V first element and C 2nd col by V 2nd element.
Matrix A can have 3xN and V Nx1. Meaning (cols x rowls).
This is what I would do:
Code
Eigen::Matrix3Xf A(3, 2); // 3x2
A << 1, 2, 2, 2, 3, 5;
Eigen::Vector3f V = Eigen::Vector3f(1, 2, 3);
const Eigen::Matrix3Xf C = A.array().colwise() * V.array();
std::cout << C << std::endl;
Example output:
1 2
4 4
9 15
Explanation
You were close, the trick is to use .array() to do broadcasting multiplications.
colwiseReturnType doesn't have a .array() method, so we have to do our colwise shenanigans on the array view of A.
If you want to compute the element-wise product of two vectors (The coolest of cool cats call this the Hadamard Product), you can do
Eigen::Vector3f a = ...;
Eigen::Vector3f b = ...;
Eigen::Vector3f elementwise_product = a.array() * b.array();
Which is what the above code is doing, in a columnwise fashion.
Edit:
To address the row case, you can use .rowwise(), and you'll need an extra transpose() to make things fit
Eigen::Matrix<float, 3, 2> A; // 3x2
A << 1, 2, 2, 2, 3, 5;
Eigen::Vector2f V = Eigen::Vector2f(2, 3);
// Expected result
Eigen::Matrix<float, 3, 2> C = A.array().rowwise() * V.transpose().array();
std::cout << C << std::endl;
Example output:
2 6
4 6
6 15
In other words, you want to scale each column by a different factor, that is, apply a non uniform scaling. Scaling are best represented as a diagonal matrix, thus:
C = A * V.asDiagonal();
Since Eigen is based on expression template, this does not create any temporary and amount to a code similar to Jacob's answer:
C = A.array().rowwise() * V.transpose().array();

Trying to multiply a matrice with a constant, overload operator twice?

I'm currently trying to multiply one of the matrices in my program with a constant but as there is no existing method to do that I guess I have to overload an operator or such. But as I have already overloaded it the " * " operator once. It also needs to take the value or more specifically the constant from the left side and not from the right. How do I proceed?
All help is appreciated!
The overloaded * operator
matrix operator * (matrix const arg){
double sum = 0;
int x = 0;
int rowY = 0;
int rowX = 0;
this->matrix_array_multiply = new double[row*arg.col];
for (int position = 0; position < row*arg.col; position++, x++){
if (arg.matrix_array[x*arg.row] == (arg.matrix_array[arg.row*arg.col])){
//If last number in second matrix, reset these values and proceed with next row of Y-values.
x = 0;
rowY++;
}
for (int y = 0; y < arg.row; y++, rowX++){
sum = sum + (matrix_array[y + (rowY*col)]) * (arg.matrix_array[x + (rowX*arg.col)]);
}
matrix_array_multiply[position] = sum;
rowX = 0;
sum = 0;
}
matrix new_matrix_multiply(matrix_array_multiply, row, arg.col); //Create new instance of new matrix.
return new_matrix_multiply; //Return new matrix.
}
Usage of the different matrices and operators:
int main () {
double a[] = { 3, 0, 3, 4,
3, 4, 2, 4,
5, 3, 2, 1 };
double b[] = { 6, 3, 5, 7,
9, 8, 6, 4,
6, 5, 3, 1 };
double c[] = { 1, 2, 3, 4,
5, 6, 7, 8,
9, 2, 1, 1,};
double d[] = { 6, 5, 4, 3,
2, 1, 0, 1,
2, 3, 4, 5,
6, 7, 8, 9};
double e[] = { 1, 2, 1,
3, 5, 7,
9, 7, 3};
matrix matrix1(a, 3, 4); //Instance of the class matrix: array, rows, columns.
matrix matrix2(b, 3, 4);
matrix matrix3(c, 3, 4);
matrix matrix4(d, 4, 4);
matrix matrix5(e, 3, 3);
matrix matrix6 = (matrix1 + matrix2);
matrix matrix7 = (matrix2 - matrix1);
matrix matrix8 = (matrix3 * matrix4);
matrix matrix9 = ~matrix5;
matrix matrix10 = (5.7 * matrix5); // Error: no operator "*" matches these operands, operand types are: double * matrix
}
Note: I've just started to learn c++ and this is part of a homework.
matrix matrix10 = (5.7 * matrix5);
For this to work, you've to define a free function with this signature:
matrix operator*(double c, matrix const & m) //non-member function
{
//your code
}
And likewise, you would like to define this also:
matrix operator*(matrix const & m, double c)
{
return c * m; //call the other overload!
}

Elegant way the find the Vertices of a Cube

Nearly every OpenGL tutorial lets you implement drawing a cube. Therefore the vertices of the cube are needed. In the example code I saw a long list defining every vertex. But I would like to compute the vertices of a cube rather that using a overlong list of precomputed coordinates.
A cube is made of eight vertices and twelve triangles. Vertices are defined by x, y, and z. Triangles are defined each by the indexes of three vertices.
Is there an elegant way to compute the vertices and the element indexes of a cube?
When i was "porting" the csg.js project to Java I've found some cute code which generated cube with selected center point and radius. (I know it's JS, but anyway)
// Construct an axis-aligned solid cuboid. Optional parameters are `center` and
// `radius`, which default to `[0, 0, 0]` and `[1, 1, 1]`. The radius can be
// specified using a single number or a list of three numbers, one for each axis.
//
// Example code:
//
// var cube = CSG.cube({
// center: [0, 0, 0],
// radius: 1
// });
CSG.cube = function(options) {
options = options || {};
var c = new CSG.Vector(options.center || [0, 0, 0]);
var r = !options.radius ? [1, 1, 1] : options.radius.length ?
options.radius : [options.radius, options.radius, options.radius];
return CSG.fromPolygons([
[[0, 4, 6, 2], [-1, 0, 0]],
[[1, 3, 7, 5], [+1, 0, 0]],
[[0, 1, 5, 4], [0, -1, 0]],
[[2, 6, 7, 3], [0, +1, 0]],
[[0, 2, 3, 1], [0, 0, -1]],
[[4, 5, 7, 6], [0, 0, +1]]
].map(function(info) {
return new CSG.Polygon(info[0].map(function(i) {
var pos = new CSG.Vector(
c.x + r[0] * (2 * !!(i & 1) - 1),
c.y + r[1] * (2 * !!(i & 2) - 1),
c.z + r[2] * (2 * !!(i & 4) - 1)
);
return new CSG.Vertex(pos, new CSG.Vector(info[1]));
}));
}));
};
I solved this problem with this piece code (C#):
public CubeShape(Coord3 startPos, int size) {
int l = size / 2;
verts = new Coord3[8];
for (int i = 0; i < 8; i++) {
verts[i] = new Coord3(
(i & 4) != 0 ? l : -l,
(i & 2) != 0 ? l : -l,
(i & 1) != 0 ? l : -l) + startPos;
}
tris = new Tris[12];
int vertCount = 0;
void AddVert(int one, int two, int three) =>
tris[vertCount++] = new Tris(verts[one], verts[two], verts[three]);
for (int i = 0; i < 3; i++) {
int v1 = 1 << i;
int v2 = v1 == 4 ? 1 : v1 << 1;
AddVert(0, v1, v2);
AddVert(v1 + v2, v2, v1);
AddVert(7, 7 - v2, 7 - v1);
AddVert(7 - (v1 + v2), 7 - v1, 7 - v2);
}
}
If you want to understand more of what is going on, you can check out the github page I wrote that explains it.