I want to find diagonal elements of R matrix obtained from QR-decomposition of A matrix as A=QR using lapack. I tried lapack dgeqrf subroutine but it is giving back the same matrix A i.e. input and output matrices are same. How to find R matrix and its diagonals ? I can't figure out what is going wrong with this code. I am programming in C.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void dgeqrf_(int *rows, int *cols, double *matA, int *LDA, double *TAU, double *WORK, int *LWORK, int *INFO);
int main()
{
int rows=3;
int cols=3;
double *matA=malloc(sizeof(double)*rows*cols);
matA[0]=10;
matA[1]=20;
matA[2]=10;
matA[3]=40;
matA[4]=20;
matA[5]=50;
matA[6]=70;
matA[7]=30;
matA[8]=20;
for(int i=0; i<rows*cols; i++)
{
printf("%f ",matA[i]);
}
printf("\n");
int LDA=rows;
int INFO;
double *WORK=malloc(sizeof(double)*2);
int LWORK=-1;
int rowcolmin=rows;
if(rowcolmin>cols)
{
rowcolmin=cols;
}
double *TAU=malloc(sizeof(double)*rowcolmin);
dgeqrf_(&rows, &cols, matA, &LDA, TAU, WORK, &LWORK, &INFO);
for(int i=0; i<rows*cols; i++)
{
printf("%f ",matA[i]);
}
printf("\n");
free(WORK);
free(TAU);
free(matA);
return 0;
}
The matrix matA is not modified because LAPACK's dgeqrf() is called using a value of -1 for the argument LWORK. This correspond to a workspace query:
If LWORK = -1, then a workspace query is assumed; the routine
only calculates the optimal size of the WORK array, returns
this value as the first entry of the WORK array, and no error
message related to LWORK is issued by XERBLA.
Indeed, the usual way to use dgeqrf() and many other routines from LAPACK is to call them twice: once for the workspace query and once for the actual computation of the result. For instance, the C interface to LAPACK wraps dgeqrf() in lapacke__dgeqrf(), which calls lapacke__dgeqrf_work() twice for this very reason.
Here is how your code could be modified:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void dgeqrf_(int *rows, int *cols, double *matA, int *LDA, double *TAU, double *WORK, int *LWORK, int *INFO);
int main()
{
int i;
int rows=3;
int cols=3;
double *matA=malloc(sizeof(double)*rows*cols);
matA[0]=1;
matA[1]=2;
matA[2]=4;
matA[3]=1;
matA[4]=3;
matA[5]=9;
matA[6]=1;
matA[7]=4;
matA[8]=16;
for(i=0; i<rows*cols; i++)
{
printf("%f ",matA[i]);
}
printf("\n");
int LDA=rows;
int INFO;
int rowcolmin=rows;
if(rowcolmin>cols)
{
rowcolmin=cols;
}
double *TAU=malloc(sizeof(double)*rowcolmin);
int LWORK=-1;
// since the value of LWORK is -1, this is a workspace query.
// it only return the optimum size of work in work[0].
double lwork2;
dgeqrf_(&rows, &cols, matA, &LDA, TAU, &lwork2, &LWORK, &INFO);
// allocate work using the optimal size
int lwork3=(int)lwork2;
double *WORK=malloc(sizeof(double)*lwork3);
// perform the QR factorization
dgeqrf_(&rows, &cols, matA, &LDA, TAU, WORK, &lwork3, &INFO);
if(INFO !=0){fprintf(stderr,"QR factorization failed, error code %d\n",INFO);exit(1);}
for(i=0; i<rows*cols; i++)
{
printf("%f ",matA[i]);
}
printf("\n");
// for instance, the determinant is...
if(cols==rows){
// det of R
double det=1;
for (i=0;i<cols;i++){
det*=matA[i*cols+i];
}
// det of Q, Householder algorithm
if(cols%2==0){
det*=-1;
}
printf("det is %g\n",det);
}
free(WORK);
free(TAU);
free(matA);
return 0;
}
It is compiled by gcc main.c -o main -llapack -lblas -lm.
Given the question you asked, entitled compute determinant from LU decomposition in lapack , the computation of the determinant is added at the end of the code. The matrix matA is now a Vandermonde matrix, so as to easily check the correctness of the result.
Related
I have encountered an issue when using Eigen in MATLAB MEX files.
Consider this excerpt of code, in which I call a mex function to create an object of the class vars. The class has an integer N, an integer S, and two Eigen arrays.
//constructMat.cpp
class vars {
public:
int N
int S
Eigen::ArrayXd upperLims
Eigen::ArrayXd lowerLims
stateVars (double *, double *, double *)
};
stateVars::stateVars (double *upperInput, double *lowerInput, double *gridInput)
Eigen::ArrayXd upper; upper = Eigen::Map<Eigen::VectorXd>(upperInput, sizeof(*upperInput),1);
Eigen::ArrayXd lower; lower = Eigen::Map<Eigen::VectorXd>(lowerInput, sizeof(*lowerInput),1);
Eigen::ArrayXd gridSizes; gridSizes = Eigen::Map<Eigen::VectorXd>(gridInput, sizeof(*gridInput),1);
upperLims = upper;
lowerLims = lower;
N = upperLims.size();
S = gridSizes.prod();
}
//MEX CODE
void
mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
//....checks to make sure the inputs are okay...
double* upper = mxGetPr(prhs[0]);
double* lower = mxGetPr(prhs[1]);
double* grids = mxGetPr(prhs[2]);
stateVars stateSpace(upper, lower, grids);
mexPrintf("N =%f \n\n", stateSpace.N );
mexPrintf("S =%f \n\n", stateSpace.S );
}
However, when I execute the function, I call constructMat([7.0, 8.0, 9.0], [4.0, 2.0, 3.0], [10, 10, 10]), and I expect mexPrintf("N =%f \n\n", stateSpace.N ) to yield 3 since the array upperLims only has three elements. However, it yields 7. Similarly, I expect mexPrintf("S =%f \n\n", stateSpace.S ) to yield 10^3 = 1000, but it yields 7 as well. I'm not sure what I did wrong. The mex file was compiled successfully.
Also, if I call mexPrintf("upperlims =%f \n\n",stateSpace.upperLims(0) ), i.e. printing out the first element of the Eigen array upperLims, it gives me the right number. Does it have something to do with the method .size() and .prod()?
I am trying to create an online palindrome sensor(The alphabet consists of 0,1,2,3,...9). The code is as follows:
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int x=0;
int y=0;
int c;
int i=0;
while(1)
{
cin>>c;
//I keep a track of previous number in x and its reverse in y and use them to create the
//the new number and reverse at every input. Then I compare x and y. If equal the number is
//a palindrome.
/*eg:(When 121 is entered digit by digit)
i=0:-
x=10*0+1 y=0+ 10^0 *1
i=1:-
x=10*1+2 y=1+ 10^1 *2
i=2:-
x=10*12+1 y=21+ 10^2 *1
*/
x=10*x+c;
y=y+ static_cast<int>(pow(10.0,static_cast<double>(i)) *c);
cout<<"y= "<<y<<" and "<<"x= "<<x<<endl;
if(y==x)
cout<<"Palindrome"<<endl;
i++;
}
return 0;
}
First, I enter 1 and it was indicated as palindrome(as expected). Then, I entered 2 and nothing happened(as expected, 'y= 21 and x= 12' was printed). But, then I again entered 1 and this time too nothing happened(not as expected) and this was printed:
y= 120 and x= 121
Can anyone tell me, how did y become 120 when it was supposed to be 121?
You are doing far too much math:
public static boolean isPalindrom(char[] word){
int i1 = 0;
int i2 = word.length - 1;
while (i2 > i1) {
if (word[i1] != word[i2]) {
return false;
}
++i1;
--i2;
}
return true;
}
All you need to do is fill an array with values as the user enters them and invoke a function similar to this. The use of exponents is a colossal waste of resources when simpler solutions exist.
I wrote the following C/MEX code using the FFTW library to control the number of threads used for a FFT computation from MATLAB. The code works great (complex FFT forward and backward) with the FFTW_ESTIMATE argument in the planner although it is slower than MATLAB. But, when I switch to the FFTW_MEASURE argument to tune up the FFTW planner, it turns out that applying one FFT forward and then one FFT backward does not return the initial image. Instead, the image is scaled by a factor. Using FFTW_PATIENT gives me an even worse result with null matrices.
My code is as follows:
Matlab functions:
FFT forward:
function Y = fftNmx(X,NumCPU)
if nargin < 2
NumCPU = maxNumCompThreads;
disp('Warning: Use the max maxNumCompThreads');
end
Y = FFTN_mx(X,NumCPU)./numel(X);
FFT backward:
function Y = ifftNmx(X,NumCPU)
if nargin < 2
NumCPU = maxNumCompThreads;
disp('Warning: Use the max maxNumCompThreads');
end
Y = iFFTN_mx(X,NumCPU);
Mex functions:
FFT forward:
# include <string.h>
# include <stdlib.h>
# include <stdio.h>
# include <mex.h>
# include <matrix.h>
# include <math.h>
# include </home/nicolas/Code/C/lib/include/fftw3.h>
char *Wisfile = NULL;
char *Wistemplate = "%s/.fftwis";
#define WISLEN 8
void set_wisfile(void)
{
char *home;
if (Wisfile) return;
home = getenv("HOME");
Wisfile = (char *)malloc(strlen(home) + WISLEN + 1);
sprintf(Wisfile, Wistemplate, home);
}
fftw_plan CreatePlan(int NumDims, int N[], double *XReal, double *XImag, double *YReal, double *YImag)
{
fftw_plan Plan;
fftw_iodim Dim[NumDims];
int k, NumEl;
FILE *wisdom;
for(k = 0, NumEl = 1; k < NumDims; k++)
{
Dim[NumDims - k - 1].n = N[k];
Dim[NumDims - k - 1].is = Dim[NumDims - k - 1].os = (k == 0) ? 1 : (N[k-1] * Dim[NumDims-k].is);
NumEl *= N[k];
}
/* Import the wisdom. */
set_wisfile();
wisdom = fopen(Wisfile, "r");
if (wisdom) {
fftw_import_wisdom_from_file(wisdom);
fclose(wisdom);
}
if(!(Plan = fftw_plan_guru_split_dft(NumDims, Dim, 0, NULL, XReal, XImag, YReal, YImag, FFTW_MEASURE *(or FFTW_ESTIMATE respectively)* )))
mexErrMsgTxt("FFTW3 failed to create plan.");
/* Save the wisdom. */
wisdom = fopen(Wisfile, "w");
if (wisdom) {
fftw_export_wisdom_to_file(wisdom);
fclose(wisdom);
}
return Plan;
}
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
{
#define B_OUT plhs[0]
int k, numCPU, NumDims;
const mwSize *N;
double *pr, *pi, *pr2, *pi2;
static long MatLeng = 0;
fftw_iodim Dim[NumDims];
fftw_plan PlanForward;
int NumEl = 1;
int *N2;
if (nrhs != 2) {
mexErrMsgIdAndTxt( "MATLAB:FFT2mx:invalidNumInputs",
"Two input argument required.");
}
if (!mxIsDouble(prhs[0])) {
mexErrMsgIdAndTxt( "MATLAB:FFT2mx:invalidNumInputs",
"Array must be double");
}
numCPU = (int) mxGetScalar(prhs[1]);
if (numCPU > 8) {
mexErrMsgIdAndTxt( "MATLAB:FFT2mx:invalidNumInputs",
"NumOfThreads < 8 requested");
}
if (!mxIsComplex(prhs[0])) {
mexErrMsgIdAndTxt( "MATLAB:FFT2mx:invalidNumInputs",
"Array must be complex");
}
NumDims = mxGetNumberOfDimensions(prhs[0]);
N = mxGetDimensions(prhs[0]);
N2 = (int*) mxMalloc( sizeof(int) * NumDims);
for(k=0;k<NumDims;k++) {
NumEl *= NumEl * N[k];
N2[k] = N[k];
}
pr = (double *) mxGetPr(prhs[0]);
pi = (double *) mxGetPi(prhs[0]);
//B_OUT = mxCreateNumericArray(NumDims, N, mxDOUBLE_CLASS, mxCOMPLEX);
B_OUT = mxCreateNumericMatrix(0, 0, mxDOUBLE_CLASS, mxCOMPLEX);
mxSetDimensions(B_OUT , N, NumDims);
mxSetData(B_OUT , (double* ) mxMalloc( sizeof(double) * mxGetNumberOfElements(prhs[0]) ));
mxSetImagData(B_OUT , (double* ) mxMalloc( sizeof(double) * mxGetNumberOfElements(prhs[0]) ));
pr2 = (double* ) mxGetPr(B_OUT);
pi2 = (double* ) mxGetPi(B_OUT);
fftw_init_threads();
fftw_plan_with_nthreads(numCPU);
PlanForward = CreatePlan(NumDims, N2, pr, pi, pr2, pi2);
fftw_execute_split_dft(PlanForward, pr, pi, pr2, pi2);
fftw_destroy_plan(PlanForward);
fftw_cleanup_threads();
}
FFT backward:
This MEX function differs from the above only in switching pointers pr <-> pi, and pr2 <-> pi2 in the CreatePlan function and in the execution of the plan, as suggested in the FFTW documentation.
If I run
A = imread('cameraman.tif');
>> A = double(A) + i*double(A);
>> B = fftNmx(A,8);
>> C = ifftNmx(B,8);
>> figure,imagesc(real(C))
with the FFTW_MEASURE and FFTW_ESTIMATE arguments respectively I get this result.
I wonder if this is due to an error in my code or in the library. I tried different thing around the wisdom, saving not saving. Using the wisdom produce by the FFTW standalone tool to produce wisdom. I haven't seen any improvement. Can anyone suggest why this is happening?
Additional information:
I compile the MEX code using static libraries:
mex FFTN_Meas_mx.cpp /home/nicolas/Code/C/lib/lib/libfftw3.a /home/nicolas/Code/C/lib/lib/libfftw3_threads.a -lm
The FFTW library hasn't been compiled with:
./configure CFLAGS="-fPIC" --prefix=/home/nicolas/Code/C/lib --enable-sse2 --enable-threads --&& make && make install
I tried different flags without success. I am using MATLAB 2011b on a Linux 64-bit station (AMD opteron quad core).
FFTW computes not normalized transform, see here:
http://www.fftw.org/doc/What-FFTW-Really-Computes.html
Roughly speaking, when you perform direct transform followed by inverse one, you get
back the input (plus round-off errors) multiplied by the length of your data.
When you create a plan using flags other than FFTW_ESTIMATE, your input is overwritten:
http://www.fftw.org/doc/Planner-Flags.html
I have the following kernel
__global__ void func( float * arr, int N ) {
int rtid = blockDim.x * blockIdx.x + threadIdx.x;
if( rtid < N )
{
float* row = (float*)((char*)arr + rtid*N*sizeof(float) );
for (int c = 1; c < N; ++c)
{
//Manipulation
}
}
}
When I call the kernel from MATLAB using
gtm= parallel.gpu.GPUArray(ones(a,b,'double'));
OR gtm= parallel.gpu.GPUArray(ones(1,b,'double'));
gtm=k.feval(gtm,b);
it is giving the following error:
Error using ==> feval
parallel.gpu.GPUArray must match the exact input type as specified on the kernel
prototype.
Error in ==> sameInit at 65 gtm=k.feval(gtm,b);
Can someone please tell me where am I going wrong.
Thanking You,
Viharri P L V.
The kernel object "k" that is being created in MATLAB have the following structure:
MaxNumLHSArguments: 1
NumRHSArguments: 2
ArgumentTypes: {'inout single' 'in int32 scalar'}
with the above mentioned CUDA kernel prototype i.e.,
__global__ void func( float * arr, int N )
So, there was an mismatch error. We need to either change the prototype of the CUDA kernel to
__global__ void func( double * arr, int N )
or create the MATLAB array with 'single' type.
gtm= parallel.gpu.GPUArray(ones(a,b,'single'));
I have a question about using fgetc to count characters in a specified file.
How do you use it when you have to count character types separately? Like for example I only want to count the number of lowercase characters only, or number of spaces, or punctuations, etc? Can someone show a brief example? Thank you
I tried to do this program that would hopefully count the total number of characters, how do you squeeze in though the number of the separate character types? I'm not exactly sure if this program is correct
#include <stdio.h>
int main (void)
{
//Local declarations
int a;
int count = 0;
FILE* fp;
//Statements
if (!(fp = fopen("piFile.c", "r")))
{
printf("Error opening file.\n");
return (1);
}//if open error
while ((a = fgetc (fp)) != EOF)
{
if (a != '\n')
count++;
printf("Number of characters: %d \n", count);
else
printf("There are no characters to count.\n");
}
fclose(fp);
return 0;
}
Read up on these functions:
int isalnum(int c);
int isalpha(int c);
int isascii(int c);
int isblank(int c);
int iscntrl(int c);
int isdigit(int c);
int isgraph(int c);
int islower(int c);
int isprint(int c);
int ispunct(int c);
int isspace(int c);
int isupper(int c);
int isxdigit(int c);
and you'll see right away how to do it.
In your while, you can use if statements for each character you want to check.
if(isalnum(a){
counta++;
}
else if(isalpha(a)){
countb++;
}
else if(isascii(a)){
countc++;
}