I have recently installed a new library for matrix calculation in C++, called LAPACK. I am beginner in this field and wanted to test its application in QR decomposition by using the dgeqrf function. I prepared this simple code below:
#include <iostream>
#include <lapacke.h>
using namespace std;
int main()
{
double a[4] = {0, 2, 2, -1};
int m=2;
int n=2;
int info = 0;
int lda = m;
int lwork = n;
double *work;
double *tau;
dgeqrfp_(&m, &n, a, &lda, tau, work, &lwork, &info);
}
I built it without error but when I tried to run it, it didn't work. I got these warning messages:
D:\c++ code\lllll\main.cpp|15|warning: 'tau' is used uninitialized in this function [-Wuninitialized]|
D:\c++ code\lllll\main.cpp|15|warning: 'work' is used uninitialized in this function [-Wuninitialized]|
I don't know what's the problem but I think my definition of the dgeqrf function is wrong.
Also, the dgeqrf is a void function. I need to save its result (Q matrix) into an another matrix and use it in my calculation.
Does anyone have an idea about it?
As stated in the docs, TAU and WORK are supposed to be arrays the function can work on.
In particular, WORK shall be an array of double and have (at least) length LWORK, it is used as internal temporary memory.
TAU is an array used to output the elementary reflectors of the QR decomposition and shall have length (at least) min(n,m).
So your complete call would look something like this:
#include <iostream>
#include <lapacke.h>
using namespace std;
int main()
{
double a[4] = {0,2,2,-1};
int m=2;
int n=2;
int info = 0;
int lda = m;
int lwork = n;
double work[2];
double tau[2];
dgeqrfp_(&m, &n, a, &lda, tau, work, &lwork, &info);
}
Related
i initialize the matrix and call the output like this in int main()
int array[a][b][c] = {0};
OMat3(a,b,c,(int*)array);
this is the output function
void OMat3(int rig,int col,int pro,int *mat){
for (int a=0;a<rig;a++){
printf("\n%da Materia:\n",a+1);
for (int b=0;b<col;b++){
printf("\n\t%d Giorno: ",b+1);
for (int c=0;c<pro;c++){
printf("%d ",mat[a*col*pro+b*pro+c]);
}
}
}
}
the problem is that in the output i don't get only 0s (there are mostly 0, but sometimes there are crazy high values).
Am I initializing it to 0 wrong or is there something wrong with my output function?
example program
void OMat3(int rig,int col,int pro,int *mat){
for (int a=0;a<rig;a++){
printf("\nRow %d:\n",a+1);
for (int b=0;b<col;b++){
printf("\n\tColumn %d: ",b+1);
for (int c=0;c<pro;c++){
printf("%d ",mat[a*col*pro+b*pro+c]);
}
}
}
}
int main(){
int a,b,c;
printf("Insert the array's dimensions: ");
scanf("%d %d %d",&a,&b,&c);
int array[a][b][c] = {0};
OMat3(a,b,c,(int*)array);
}
I'm using TDM-GCC 4.9.2 64-bit Release if that's important
First, this is not legal C++ syntax:
int a,b,c;
//...
int array[a][b][c] = {0};
The issue is that C++ does not allow declaring arrays with a variable being used as the number of items. So a, b, or c cannot be used in the array declaration. An array's size must be declared using a compile-time expression, not a value determined at runtime.
What you are using is an extension offered by GCC, namely Variable Length Arrays. If you compiled your code using -Wall -pedantic flags for g++, you will get the error that I am speaking of.
The way you can alleviate this is to use std::vector<int>.
#include <vector>
//..
int a, b, c;
//..assume a, b, and c have values
std::vector<int> array(a*b*c);
//... call the function
OMat3(a, b, c, array.data());
Using array[a][b][c]={} works as intended and initializes all of the values to 0
Thanks to #AndyG for finding out that.
I tried several time to find where is the problem, but I can not find any thing.So, could anyone help me to find the problem and why I can not see a result?
It might seem stupid question, but I new to programming world :)
This is my code :
#include <iostream>
using namespace std;
// There is the declraction of all functions
float max();
float min();
// This is the main program
int main ( int argc, char ** argv )
{
// Here you can find max
max(504.50,70.33);
// Here you can find min
min(55.77, 80.12);
return 0;
}
// This is the max function
int max(float a, float b){
float theMax;
if (a>b) {
theMax = a;
cout <<theMax ;
}
else{
theMax = b;
cout << b;
}
return theMax;
}
// This is the min function
int min( float c, float d){
float theMin;
if (c >d ) {
theMin =c;
cout << theMin;
}
else {
theMin =d;
cout << theMin;
}
return theMin;
}
You're calling std::max and std::min. That's because you wrote using namespace std, and did not declare your own min and max prior to using them. (You did declare two other min and max functions, but those take zero arguments, not two). So, when the compiler sees max(504.50,70.33); the only candidate is std::max.
You declare these overloads:
float max();
float min();
which are functions that take no arguments and return float.
You're calling
max(504.50,70.33);
and
min(55.77, 80.12);
which are functions that takes two doubles and may or may not return anything.
These match std::max and std::min, not the prototypes you declared.
You then define
int min( float c, float d){
which also doesn't match the prototypes you declared.
In other words, these functions are unknown in main, and the functions that are actually called are std::min and std::max.
Don't use using namespace std; - what you save in typing is lost in clarity and debugging.
You should also rename the functions - it's not a good idea to reuse standard library names.
Please help solving the compile time error. I have the declaration in different files as shown below
type.h
extern block posTime(const int row[MAX_ROW], int Flag, int n,double Time[]=0 );
a.cc
block posTime( const int row[MAX_ROW],
int Flag,
int n,
double* eraseTime[]
)
...
eraseTime[0]=test[1];
..
b.cc
...
double eraseTime[MAX_ROW];
block newB = posTime (0,0,0,&eraseTime);
the last line block newB = posTime (0,0,0,&eraseTime); gives me the error, cannot convertdouble (*)[10] to double* for argument 4
I want to upadte the eraseTime in a.cc and use back in b.cc. Can I do that?
Working solution (GCC 4.9.0 with C++11)
test.hpp
#define MAX_ROW 10
extern double posTime(const int row[MAX_ROW], int Flag, int n,double Time[]=0 );
test1.cpp
#include "test.hpp"
double posTime( const int row[MAX_ROW],
int Flag,
int n,
double* eraseTime
)
{ eraseTime[0] = 2; eraseTime[1] = 3; return eraseTime[0]; }
test.cpp
#include <iostream>
#include "test.hpp"
double eraseTime[MAX_ROW] { 1, 2, 3, 4, 5, 6 ,7, 8, 9, 10 };
int main() {
double newB = posTime (0,0,0,eraseTime);
std::cout << "result: " << newB << std::endl;
for (auto v : eraseTime) {
std::cout << v << std::endl;
}
return 0;
}
compilation command:
g++ -std=c++11 -o e:\test.exe e:\test.cpp e:\test1.cpp
or double eraseTime[MAX_ROW], if you are using MAX_ROW in int row i don't see why not in eraseTime (probably some call location not in the sample restrict this use) or double* eraseTime.
Recommended change to use std::array (constant size) or std::vector (dynamic size).
There are multiple issues here:
The signature in the header and in the implementation file are not the same: The header declares the last argument of posTime() to be of type double* (yes, pointer, not array!), while the implementation declares it to be of type double** (again, the array specification is converted to a pointer declaration because it is a function argument declaration).
The result is, that the implementation declares an overload to the function declared in the header, not an implementation for it.
When you take the address of an array, you get a pointer to an array, i. e. a value of type double (*)[MAX_ROW]. This is incompatible to a double**, which is what your compiler is complaining about. To create a variable of this type, you must use the syntax double (*myArrayPointer)[MAX_ROW];. The parentheses are important because the array subscript operator has a higher precedence than the dereference operator, with the consequence that double* myPointerArray[MAX_ROW]; declares an array of MAX_ROW pointers to doubles.
If you want to pass the array as a pointer to an array, you need to declare your function as
extern block posTime(const int row[MAX_ROW], int Flag, int n,double (*Time)[MAX_ROW]=0 );
This has the advantage that you get type checking on the length of the array, but the disadvantage that you cannot accept arrays of dynamic size. If you need this flexibility, the normal approach is to pass a pointer to the first element:
extern block posTime(const int row[MAX_ROW], int Flag, int n,double *Time=0 );
called with
block newB = posTime (0,0,0,eraseTime);
The call relies on array-pointer-decay to make a double* from your array identifier.
When I return pointer from the function, its value can be accessed individually. But when a loop is used to ouput the value of that pointer variable, wrong value is shown. Where I am making mistake, can't figure it out.
#include <iostream>
#include <conio.h>
int *cal(int *, int*);
using namespace std;
int main()
{
int a[]={5,6,7,8,9};
int b[]={0,3,5,2,1};
int *c;
c=cal(a,b);
//Wrong outpur here
/*for(int i=0;i<5;i++)
{
cout<<*(c+i);
}*/
//Correct output here
cout<<*(c+0);
cout<<*(c+1);
cout<<*(c+2);
cout<<*(c+3);
cout<<*(c+4);
return 0;
}
int *cal(int *d, int *e)
{
int k[5];
for(int j=0;j<5;j++)
{
*(k+j)=*(d+j)-*(e+j);
}
return k;
}
You are returning a pointer to a local variable.
k is created on the stack. When cal() exits the stack is unwound and that memory is free'd. Referencing that memory afterwards leads to undefined behaviour (as explained beautifully here: https://stackoverflow.com/a/6445794/78845).
Your C++ compiler should warn you about this and you should heed these warnings.
For what it's worth, here is how I'd implement this in C++:
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
int main()
{
int a[] = {5, 6, 7, 8, 9};
int b[] = {0, 3, 5, 2, 1};
int c[5];
std::transform (a, a + 5, b, c, std::minus<int>());
std::copy(c, c + 5, std::ostream_iterator<int>(std::cout, ", "));
}
See it run!
The int k[5] array is created on the stack. So it gets destroyed when it goes out of scope by returning from cal. You could use a third parameter as an output array:
void cal(int *d, int *e, int* k)
{
for(int j=0;j<5;j++)
{
*(k+j)=*(d+j)-*(e+j);
}
}
call cal like this:
int a[]={5,6,7,8,9};
int b[]={0,3,5,2,1};
int c[5];
cal (a, b, c); // after returning from cal, c will be populated with desired values
As others have pointed out, you're returning a pointer to a local
variable, which is undefined behavior. The real problem, however, is
that you need to return an array, and C style arrays are broken.
Replace your arrays with std::vector<int>, forget about the pointers
(because you're dealing with values), and the code will work.
I have been exploring algorithms that require some work on matrices, and I have gotten some straightforward code working on my Linux machine. Here is an excerpt:
extern "C" {
// link w/ LAPACK
extern void dpptrf_(const char *uplo, const int *n, double *ap, int *info);
extern void dpptri_(const char *uplo, const int *n, double *ap, int *info);
// BLAS todo: get sse2 up in here (ATLAS?)
extern void dgemm_(const char *transa, const char *transb, const int *m,
const int *n, const int *k, const double *alpha, const double *a,
const int *lda, const double *b, const int *ldb, const double *beta,
double *c, const int *ldc);
}
// in-place: be sure that (N*(N+1)/2) doubles have been initialized
inline void invert_mat_sym_packed(double *vd, int n) {
int out = 0;
dpptrf_("U",&n,vd,&out);
ASSERT(!out);
dpptri_("U",&n,vd,&out);
ASSERT(!out);
}
// use with col-major ordering!!!
inline void mult_cm(double *a, double *b, double alpha, int m, int k, int n, double *c) {
int lda = m, ldb = k, ldc = m; double beta = 1.0;
dgemm_("N","N",&m,&n,&k,&alpha,a,&lda,b,&ldb,&beta,c,&ldc);
}
all I had to do was sudo apt-get install liblapack, and link against the library.
I am now trying to get this code working from MinGW using the 32-bit dll's from here but I am seeing segfaults and invalid output. I will proceed with gdb to determine the location of the error but I suspect there's a better, cleaner, more portable way to get this done.
What I did to get it to compile was install fortran for mingw (mingw-get install fortran) and link to the 32bit BLAS and LAPACK dll's from the earlier link.
I'm not sure how much I'm missing here... How does everybody else get their LAPACK going when coding with gcc for win32?
What I'm looking for is an easy-to-use C interface. I don't want wrapper classes all over the place.
I tried to find a download for Intel MKL... Ain't even free software!?
I solved the problem. It had nothing to do with the way I was calling the routines, I failed to memset my buffers to zero prior to accumulating values onto them.
Calling fortran routines is basically just as straightforward as it is to do from Linux.
However, another rather serious problem has appeared: Once I use the lapack routines my program no longer handles exceptions. See here.