I wish to do exactly what rcond does in MATLAB/Octave using LAPACK from C.
The MATLAB manual tells me dgecon is used, and that is uses a 1-based norm.
I wrote a simple test program for an extremely simple case; [1,1; 1,0]
For this input matlab and octave gives me 0.25 using rcond and 1/cond(x,1), but in the case using LAPACK, this sample program prints 0.0. For other cases, such as identity, it prints the correct value.
Since MATLAB is supposely actually using this routine with success, what am I doing wrong?
I'm trying to decipher what Octave does, with little success as its wrapped in
#include <stdio.h>
extern void dgecon_(const char *norm, const int *n, const double *a,
const int *lda, const double *anorm, double *rcond, double *work,
int *iwork, int *info, int len_norm);
int main()
{
int i, info, n, lda;
double anorm, rcond;
double w[8] = { 0,0,0,0,0,0,0,0 };
int iw[2] = { 0,0 };
double x[4] = { 1, 1, 1, 0 };
anorm = 2.0; /* maximum column sum, computed manually */
n = 2;
lda = 2;
dgecon_("1", &n, x, &lda, &anorm, &rcond, w, iw, &info, 1);
if (info != 0) fprintf(stderr, "failure with error %d\n", info);
printf("%.5e\n", rcond);
return 0;
}
Compiled with cc testdgecon.c -o testdgecon -llapack; ./testdgecon
I found the answer to me own question.
The matrix is must be LU-decomposed before it is sent to dgecon. This seems very logical since one often wants to solve the system after checking the condition, in which case there is no need to decompose the matrix twice. The same idea goes for the norm which is computed separately.
The following code is all the necessary parts the compute the reciprocal condition number with LAPACK.
#include "stdio.h"
extern int dgecon_(const char *norm, const int *n, double *a, const int *lda, const double *anorm, double *rcond, double *work, int *iwork, int *info, int len);
extern int dgetrf_(const int *m, const int *n, double *a, const int *lda, int *lpiv, int *info);
extern double dlange_(const char *norm, const int *m, const int *n, const double *a, const int *lda, double *work, const int norm_len);
int main()
{
int i, info, n, lda;
double anorm, rcond;
int iw[2];
double w[8];
double x[4] = {7,3,-9,2 };
n = 2;
lda = 2;
/* Computes the norm of x */
anorm = dlange_("1", &n, &n, x, &lda, w, 1);
/* Modifies x in place with a LU decomposition */
dgetrf_(&n, &n, x, &lda, iw, &info);
if (info != 0) fprintf(stderr, "failure with error %d\n", info);
/* Computes the reciprocal norm */
dgecon_("1", &n, x, &lda, &anorm, &rcond, w, iw, &info, 1);
if (info != 0) fprintf(stderr, "failure with error %d\n", info);
printf("%.5e\n", rcond);
return 0;
}
Related
I am using the montecarlo method as implemented in the gsl library. I need to compute many repetitions of this integral changing a parameter in the integrand. So I need to make my subroutine fast. It seems that the most time consuming part is the evaluation of the integrand at the random points. How could I make the evaluation faster in my specific case?
Here is a minimal example:
#include <gsl/gsl_rng.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_monte.h>
#include <gsl/gsl_monte_plain.h>
#include <gsl/gsl_monte_vegas.h>
double q=0.0;
double mu=0.001;
double eta=0.1;
double kF=1.0;
double Kcut=10;
long int Nmax=10000000;
int Nwu=1000000;
double w=1;
struct my_f_params { double y;};
double
g (double *k, size_t dim, void *p)
{
double A;
struct my_f_params * fp = (struct my_f_params *)p;
double PQ=q*q+k[1]*k[1]-2*q*k[1]*cos(k[3])+mu;
double QK=k[0]*k[0]+k[1]*k[1]-2*k[0]*k[1]* (cos(k[2])*cos(k[3])+cos(k[4])*sin(k[2])*sin(k[3]))+mu;
double KPQ=q*q+k[0]*k[0]+k[1]*k[1]+2*k[0]*cos(k[2])*(q-k[1]*cos(k[3]))+2*k[1]* (q*cos(k[3])+k[0]*cos(k[4])*sin(k[2])*sin(k[3]));
double denFreq=fp->y-0.5*(k[0]*k[0]+k[1]*k[1]+KPQ);
double vol=k[0]*k[0]*k[1]*k[1]*sin(k[2])*sin(k[3]);
if (sqrt(KPQ) < kF) {
A = vol*denFreq*(1/QK-1/PQ)/(QK*(pow(denFreq,2)+eta*eta));
}
else {
A = 0;
}
return A;
}
int
main (void)
{
double res, err;
double xl[5] = {0, kF, 0, 0, 0};
double xu[5] = {kF, Kcut, M_PI, M_PI, 2*M_PI};
const gsl_rng_type *T;
gsl_rng *r;
gsl_monte_function G;
size_t calls = Nmax;
gsl_rng_env_setup ();
struct my_f_params params;
T = gsl_rng_default;
r = gsl_rng_alloc (T);
params.y=w;
G.f=&g;
G.dim=5;
G.params=¶ms;
{
gsl_monte_vegas_state *s = gsl_monte_vegas_alloc (5);
gsl_monte_vegas_integrate (&G, xl, xu, 5, Nwu, r, s,&res, &err);
do
{
gsl_monte_vegas_integrate (&G, xl, xu, 5, calls/5, r, s,&res, &err);
}
while (fabs (gsl_monte_vegas_chisq (s) - 1.0) > 0.5);
gsl_monte_vegas_free (s);
}
printf ("%.6f %.6f %.6f\n", w,res,err);
gsl_rng_free (r);
return 0;
}
Expanding on Bob__'s comment, you can use sincos to compute the sin and cos of the same argument (k[2] and k[3]), and define a kF_sqr to be initialised in the main and use that in the g function to avoid the sqrt call. With these optimisations, a quick & dirty test on my machine showed a ~5% speed-up over your code.
I am trying to use LAPACK's dgels_ in C to solve a linear least squares problem. I have to read the matrix A (assumed to have full rank and m>=n) and a vector b from 2 text files. I can easily compile my code, but when i try to run it I get a "segmentation fault 11", but I can't really see why. It is my first time using LAPACK so I don't know if maybe I am using the dgels_ function wrong?? The way I get it the solution x will be overwritten in the vector b? :
lssolve.c:
#include <stdlib.h>
#include <stdio.h>
#include "linalg.h"
/* C prototype for LAPACK routine DGELS */
void dgels_(const char * trans, const int * m, const int * n, const int *
nrhs, double * A, const int * lda, double * B, const int * ldb, double * work,
int * lwork,int * info);
int main(int argc, char * argv[]) {
vector_t * b_t = NULL;
matrix_t * A_t = NULL;
char trans = 'N';
int m, n, nrhs, mb, lda, ldb, info, lwork;
double optwork;
double * work;
// we read the matrix A and the vector b:
b_t = read_vector("b.txt");
A_t = read_matrix("A.txt");
m = A_t-> m; //number of rows in A
n = A_t-> n; //number of columns in A
nrhs = 1; //number of columns in B (will always be 1, since we read b_t with read_vector)
mb = b_t -> n; //number of rows in B
if (mb != m ) { //end program if A and B doesn't have the same number of rows
free(A_t);
free(b_t);
fprintf(stderr, "Sorry, but the matrix A and the vector b have incompatible dimensions. Good Bye!\n");
exit(EXIT_FAILURE);
}
//We make A and B into the wanted input form for the dgels_-function:
double * B = b_t -> v;
double ** A = A_t ->A;
lda = m;
ldb = mb;
//we calculate the optimal size of the work array:
lwork = -1;
dgels_(&trans, &n, &m, &nrhs, *A, &lda, B, &ldb, &optwork, &lwork, &info);
lwork = (int)optwork;
//we allocate space for the work array:
work = (double*)malloc( lwork*sizeof(double));
//solving the least squares problem:
dgels_(&trans, &n, &m, &nrhs, *A, &lda, B, &ldb, work, &lwork, &info);
//Check whether there was an successful exit:
if (info > 0){
fprintf(stderr, "Sorry, but illegal arguments were used, and therefore a least square solution cannot be computes. Good Bye!\n");
exit(EXIT_FAILURE);
} else if(info < 0){
fprintf(stderr, "Sorry, but A doesn't have full rank, and therefore a least square solution cannot be computed. Good Bye!\n");
exit(EXIT_FAILURE);
}
//Saving the least square problem as a vector_t:
vector_t * x = NULL;
x->n = mb;
x->v = B;
print_vector(x);
//Free memory
free_vector(b_t);
free_matrix(A_t);
free_vector(x);
return(EXIT_SUCCESS);
}
I am using the functions read_matrix, read_vector, print_vector, print_matrix and free_vector, which is why I use the struct vector_t and matrix_t:
typedef struct vector {
unsigned long n; /* length of vector */
double * v; /* pointer to array of length n */
} vector_t;
typedef struct matrix {
unsigned long m; /* number of rows */
unsigned long n; /* number of columns */
double ** A; /* pointer to two-dimensional array */
} matrix_t;
I don't think that anything is wrong with read_vector and read_matrix because I can easily do this and use print_vector or print_matrix before I do all of the other operations.
You dereference a NULL pointer here, causing the segfault:
//Saving the least square problem as a vector_t:
vector_t * x = NULL;
x->n = mb;
x->v = B;
Maybe you should use/create a new vector_t instead of just a pointer to a vector_t?
The code below uses a recursive function called interp, but I cannot find a way to avoid using global variables for iter and fxInterpolated. The full code listing (that performs N-dimensional linear interpolation) compiles straightforwardly with:
gcc NDimensionalInterpolation.c -o NDimensionalInterpolation -Wall -lm
The output for the example given is 2.05. The code works fine but I want to find alternatives for the global variables. Any help with this would be greatly appreciated. Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int linearInterpolation(double *, double **, double *, int);
double ** allocateDoubleMatrix(int, int);
double * allocateDoubleVector(int);
void interp(int, int, double *, double *, double *);
double mult(int, double, double *, double *);
/* The objectionable global
variables that I want to get rid of! */
int iter=0;
double fxInterpolated=0;
int main(int argc, char *argv[]){
double *fx, **a, *x;
int dims=2;
x=allocateDoubleVector(dims);
a=allocateDoubleMatrix(dims,2);
fx=allocateDoubleVector(dims*2);
x[0]=0.25;
x[1]=0.4;
a[0][0]=0;
a[0][1]=1;
a[1][0]=0;
a[1][1]=1;
fx[0]=1;
fx[1]=3;
fx[2]=2;
fx[3]=4;
linearInterpolation(fx, a, x, dims);
printf("%f\n",fxInterpolated);
return (EXIT_SUCCESS);
}
int linearInterpolation(double *fx, double **a, double *x, int dims){
double *b, *pos;
int i;
b=allocateDoubleVector(dims);
pos=allocateDoubleVector(dims);
for (i=0; i<dims;i++)
b[i] = (x[i] - a[i][0]) / (a[i][1] - a[i][0]);
interp(0,dims,pos,fx,b);
return (EXIT_SUCCESS);
}
void interp(int j, int dims, double *pos, double *fx, double *b) {
int i;
if (j == dims){
fxInterpolated+=mult(dims,fx[iter],pos,b);
iter++;
return;
}
for (i = 0; i < 2; i++){
pos[j]=(double)i;
interp(j+1,dims,pos,fx,b);
}
}
double mult(int dims, double fx, double *pos, double *b){
int i;
double val=1.0;
for (i = 0; i < dims; i++){
val *= fabs(1.0-pos[i]-b[i]);
}
val *= fx;
printf("mult val= %f fx=%f\n",val, fx);
return val;
}
double ** allocateDoubleMatrix(int i, int j){
int k;
double ** matrix;
matrix = (double **) calloc(i, sizeof(double *));
for (k=0; k< i; k++)matrix[k] = allocateDoubleVector(j);
return matrix;
}
double * allocateDoubleVector(int i){
double *vector;
vector = (double *) calloc(i,sizeof(double));
return vector;
}
Thanks for the comments so far. I want to avoid the use of static. I have removed the global variable and as suggested tried parsing with the iter variable. But no joy. In addition I am getting a compile warning: "value computed is not used" with reference to *iter++; What am I doing wrong?
void interp(int j, int dims, double *pos, double *fx, double *b, int *iter) {
int i;
if (j == dims){
fxInterpolated+=mult(dims,fx[*iter],pos,b);
*iter++;
return;
}
for (i = 0; i < 2; i++){
pos[j]=(double)i;
interp(j+1,dims,pos,fx,b,iter);
}
}
There are two approaches I would consider when looking at this problem:
Keep the state in a parameter
You could use one or more variables that you pass to the function (as a pointer, if necessary) to keep the state across function calls.
For instance,
int global = 0;
int recursive(int argument) {
// ... recursive stuff
return recursive(new_argument);
}
could become
int recursive(int argument, int *global) {
// ... recursive stuff
return recursive(new_argument, global);
}
or sometimes even
int recursive(int argument, int global) {
// ... recursive stuff
return recursive(new_argument, global);
}
Use static variables
You can also declare a variable in a function to be preserved across function calls by using the static keyword:
int recursive(int argument) {
static int global = 0;
// ... recursive stuff
return recursive(argument);
}
Note that because of the static keyword, global = 0 is only set when the program starts, not every time the function is called, as it would be without the keyword. This means that if you alter the value of global, it would keep this value the next time the function is called.
This method can be used if you only use your recursive function once during your program; if you need to use it multiple times, I recommend that you use the alternative method above.
A solution is to use statics and then to reset the variables on the first call, via a flag that I call initialise. That way you can choose to have the variables reset or not.
double interp(int j, int dims, double *pos, double *fx, double *b, int initialise) {
static double fxInterpolated = 0.0;
static int iter = 0;
int i;
if (initialise){
fxInterpolated = 0.0;
iter = 0;
}
.....
......
}
The function is cyclic.c.
void cyclic(float a[], float b[], float c[], float alpha, float beta,
float r[], float x[], unsigned long n)
// Solves for a vector x[1..n] the “cyclic” set of linear equations. a,
//b, c, and r are input vectors, all dimensioned as [1..n], while alpha and beta are //the corner
// entries in the matrix.
I am new for the interface between Matlab and C. And I have not use C for several years.
Last night, I finished it and compile. The last thing is to call it.
#include "mex.h"
#include "nrutil.h"
#define FREE_ARG char*
#define NR_END 1
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define NR_END 1
#define FREE_ARG char*
void nrerror(char error_text[])
/* Numerical Recipes standard error handler */
{fprintf(stderr,"Numerical Recipes run-time error...\n");
fprintf(stderr,"%s\n",error_text);
fprintf(stderr,"...now exiting to system...\n");
exit(1);
}
float *vector(long nl, long nh)
/* allocate a float vector with subscript range v[nl..nh] */
{
float *v;
v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float)));
if (!v) nrerror("allocation failure in vector()");
return v-nl+NR_END;
}
void free_vector(float *v, long nl, long nh)
/* free a float vector allocated with vector() */
{
free((FREE_ARG) (v+nl-NR_END));
}
void tridag(float a[], float b[], float c[], float r[], float u[],
unsigned long n)
{
unsigned long j;
float bet,*gam;
gam=vector(1,n);
if (b[1] == 0.0) nrerror("Error 1 in tridag");
u[1]=r[1]/(bet=b[1]);
for (j=2;j<=n;j++) {
gam[j]=c[j-1]/bet;
bet=b[j]-a[j]*gam[j];
if (bet == 0.0) nrerror("Error 2 in tridag");
u[j]=(r[j]-a[j]*u[j-1])/bet;
}
for (j=(n-1);j>=1;j--)
u[j] -= gam[j+1]*u[j+1];
free_vector(gam,1,n);
}
void cyclic(float a[], float b[], float c[], float alpha, float beta,
float r[], float x[], unsigned long n)
{
void tridag(float a[], float b[], float c[], float r[], float u[],
unsigned long n);
unsigned long i;
float fact,gamma,*bb,*u,*z;
if (n <= 2) nrerror("n too small in cyclic");
bb=vector(1,n);
u=vector(1,n);
z=vector(1,n);
gamma = -b[1]; //Avoid subtraction error in forming bb[1].
bb[1]=b[1]-gamma; //Set up the diagonal of the modified tridiagonal
bb[n]=b[n]-alpha*beta/gamma; //system.
for (i=2;i<n;i++) bb[i]=b[i];
tridag(a,bb,c,r,x,n);// Solve A · x = r.
u[1]=gamma;// Set up the vector u.
u[n]=alpha;
for (i=2;i<n;i++) u[i]=0.0;
tridag(a,bb,c,u,z,n);// Solve A · z = u.
fact=(x[1]+beta*x[n]/gamma)/ //Form v · x/(1 + v · z).
(1.0+z[1]+beta*z[n]/gamma);
for (i=1;i<=n;i++) x[i] -= fact*z[i]; //Nowget the solution vector x.
free_vector(z,1,n);
free_vector(u,1,n);
free_vector(bb,1,n);
}
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
float *a,*b,*c,*x,*r;
float alpha,beta;
unsigned long n = (unsigned long) mxGetScalar(prhs[6]);
// a=mxGetPr(prhs[0]);
// b=mxGetPr(prhs[1]);
// c=mxGetPr(prhs[2]);
// r=mxGetPr(prhs[5]);
a = (float*) mxGetData(prhs[0]);
b = (float*) mxGetData(prhs[1]);
c = (float*) mxGetData(prhs[2]);
r = (float*) mxGetData(prhs[5]);
// alpha=*(mxGetPr(prhs[3]));
// beta=*(mxGetPr(prhs[4]));
alpha = (float) mxGetScalar(prhs[3]);
beta = (float) mxGetScalar(prhs[4]);
plhs[0]= mxCreateDoubleMatrix(n, 1, mxREAL);
x = mxGetPr(plhs[0]);
mexPrintf("%f ",alpha);
mexPrintf("\n");
mexPrintf("%f ",beta);
mexPrintf("\n");
mexPrintf("%d ",n);
mexPrintf("\n");
cyclic(a,b,c, alpha, beta,r,x,n) ;
mexPrintf("%d ",n);
mexPrintf("\n");
}
Finally I successfully compile itcyclic(a,b,c, alpha, beta,r,x,n) ;. But the answer is not right. I thing this is because r is an imaginary vector. So my question is how should I transform r between C and Matlab?
The C function cyclic expects arrays of floats, but mexFunction is passing a double*. Without changing cyclic.c, you have two options:
Convert the data to single in MATLAB and get a float* with mxGetData.
In mexFunction:
float *a = (float*) mxGetData(prhs[0]);
In MATLAB:
mexFunction(single(a),...)
Convert (copy, not cast!) the data in mexFunction.
In mexFunction, allocate new float arrays, and copy each element from the double input array (mxGetPr(prhs[0])) into the temporary float array.
Call mexFunction with a normal double array in MATLAB.
It's probably easier to do the former.
Under no circumstances should you simply cast the pointer, not that you were planning to do that.
Also, the scalars alpha, beta and n need to be read from prhs as scalars and passed to cyclic as scalars. In mexFunction, use:
float alpha = (float) mxGetScalar(prhs[...]);
float beta = (float) mxGetScalar(prhs[...]);
unsigned long n = (unsigned long) mxGetScalar(prhs[...]);
You've entirely forgotten c and r in mexFunction.
I want to use the Cubature C package to perform a multidimensional integral of a complex function. I tried to do it in the following way for the very simple function f(x,y) = x + y*i over the square [0,1]x[0,1]. The exact result is 0.5 + 0.5i.
#include <stdio.h>
#include <math.h>
#include <complex.h>
#include "../cubature.h"
int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval);
int main(void)
{
double xmin[2] = {0,0}, xmax[2] = {1,1}, val, err;
hcubature(1, f, NULL, 2, xmin, xmax, 0, 0, 1e-3, ERROR_PAIRED, &val, &err);
printf("Computed integral = %f+%fi +/- %f\n", creal(val),cimag(val), err);
}
int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval)
{
fval[0] = x[0]+x[1]*I;
return 0;
}
But what I get is Computed integral = 0.500000+0.000000i +/- 0.000000, that is the imaginary part does not appear. If I put a pure imaginary integrand (e.g. x*i) I always get 0 as result.
What am I doing wrong? Do you know any better way to compute integrals of complex functions in C?
2 issues:
1) Your are declaring double val, but you want it to be double val[2]. Your original val being a double in cimag(val) will always return 0.0. Change to
double xmin[2] = {0,0}, xmax[2] = {1,1}, val[2] /* not val */, err;
hcubature(2 /* not 1 */, f, NULL, 2, xmin, xmax, 0, 0, 1e-3, ERROR_PAIRED, /* & */val, &err);
printf("Computed integral = %f+%fi +/- %f\n", val[0], val[1], err);
2) It does not appear you are calculating f(x,y) = x + y*i correctly in f(). fval[0] is a double and can not hold the complex answer you are trying to assign.
int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval) {
fval[0] = x[0];
fval[1] = x[1];
return 0;
}
Sorry I do not have "../cubature.h" to test right now.
When you define val, do this:
double *val=(double *) malloc(sizeof(double) * integrand_fdim);
where integrand_fdim is equal to unsigned fdim - first argument of your integrand f.
P.S.: the answer by #chux produces Bus 10 or segfault...