I am doing a convolution of two integer signals with the help of FFT, but somehow I can't get it right. I am not sure if my implementation of FFT is correct. Especially the math part.
big edit:
I posted all the code now. My apologies for not starting with it. I was sure the error was only in FFT part, but there might be more problems I overlooked. I know the code is messy and not clean. Everything is a bit fragmented and can be programmed in a simpler and cleaner way, but I was testing bit by bit. As for input it reads two signals from the command line. build up as a number indicating how big the signal is and the signal presented as an integer array e.q 2: [1,-1] and 10: [0,0,0,1,1,1,1,0,0,0]. It should then do a convolution on the signals by performing a FFT on both of them then do bit wise multiplication. With a inverse FFT on the resulting signal. Printing it again with the length and then the array consiting of integers. The printing itself is correct, but the values in the resulting array is not correct. I hope it is all a bit clearer now again my apologies and thank you for your help so far.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
double PI;
int *readSignal(int *len) { //reads the signal
int *x;
char c;
scanf("%d:", len);
x = calloc(*len, sizeof(int));
do c = getchar(); while (c != '[');
if (len > 0) {
scanf("%d", &x[0]);
for (int i=1; i < *len; i++) scanf(",%d", &x[i]);
}
do c = getchar(); while (c != ']');
return x;
}
void printSignal(int len, int *x) { //prints the signal
printf("%d: [", len);
if (len > 0) {
printf("%d", x[0]);
for (int i=1; i < len; i++)
printf(",%d", x[i]);
}
printf("]\n");
}
void *padSignal(int len, int lenSig, int *x) { //ensures that the signal is of size 2^n by padding it with 0's
int *padded;
padded = calloc(len, sizeof(int));
for (int i=0; i < lenSig; i++) {
padded[i] = x[i];
}
return padded;
}
void fft(double complex signal[], int length, int power) {
if (length == 1) {
return;
}
double complex *signalODD = calloc((length/2+1), sizeof(double complex));
double complex *signalEVEN = calloc((length/2+1), sizeof(double complex));
int index1 = 0;
int index2 = 0;
for(int i = 0; i < length; i++) {
if(i % 2 ==0) {
signalEVEN[index1] = signal[i];
index1++;
}
else {
signalODD[index2] = signal[i];
index2++;
}
}
fft(signalEVEN,length/2, power+1);
fft(signalODD,length/2, power+1);
for(int i = 0; i<length/2-1; i++) {
signal[i] = signalEVEN[i] + cexp((I*2*PI*i)/length)*signalODD[i];
signal[i+length/2] = signalEVEN[i]-cexp((I*2*PI*i)/length)*signalODD[i];
}
free(signalODD);
free(signalEVEN);
}
void ifft(double complex signal[], int length, int power) {
if (length == 1) {
return;
}
double complex *signalODD = calloc((length/2+1), sizeof(double complex));
double complex *signalEVEN = calloc((length/2+1), sizeof(double complex));
int index1 = 0;
int index2 = 0;
for(int i = 0; i < length; i++) {
if(i % 2 ==0) {
signalEVEN[index1] = signal[i];
index1++;
}
else {
signalODD[index2] = signal[i];
index2++;
}
}
fft(signalEVEN,length/2, power+1);
ifft(signalODD,length/2, power+1);
for(int i = 0; i<length/2-1; i++) {
signal[i] = signalEVEN[i] + cexp((I*-2*PI*i)/length)*signalODD[i];
signal[i+length/2] = signalEVEN[i]-cexp((I*-2*PI*i)/length)*signalODD[i];
}
free(signalODD);
free(signalEVEN);
}
int checkPowerofTwo(double len) { //checks for the closed power of 2
double x = 1;
while(len > pow(2,x)) {
x++;
}
return pow(2,x);
}
int main(int argc, char *argv[]) {
int lenH, *H;
int lenX, *X;
int *paddedX;
int *paddedH;
double length;
H=readSignal(&lenH); //reads in the signal H
X=readSignal(&lenX); //reads in signal X
length = lenH+lenX-1;
paddedH=padSignal((length),lenH,H); //pads the signal to the length
paddedX=padSignal((length),lenX,X); // pads the signal to the length
double complex *signalX = calloc(length, sizeof(double complex)); //creats a complex signal X and fills it with paddedX
for (int i = 0; i<length; i++) {
signalX[i] = paddedX[i];
}
double complex *signalH = calloc(length, sizeof(double complex)); // same for H
for (int i = 0; i<length; i++) {
signalH[i] = paddedH[i];
}
fft(signalX, length, 1); //performs the fast fourier transform on X
fft(signalH,length, 1); // performs the fast fourier transfom on H
double complex *signalY = calloc(length, sizeof(double complex)); //makes complex signal Y
for (int i = 0; i<length; i++) { //performs the convolution
signalY[i] = signalX[i]*signalH[i];
}
ifft(signalY, length,1);
int *output = calloc(length, sizeof(int)); //creates the final output signal
for (int i = 0; i<length; i++) {
output[i] = creal(signalY[i]);
}
printSignal(length,output);
free(signalX);
free(signalH);
free(signalY);
free(H);
free(X);
free(paddedH);
free(paddedX);
free(output);
return 0;
}
In:
if(i % 2 ==0 && i != 0)
Why do you exclude i == 0? Change that to if(i % 2 ==0) in both fft and ifft.
In both fft and ifft, the line:
for(int i = 0; i<lenght/2-1; i++) {
should be:
for(int i = 0; i<lenght/2; i++) {
In ifft, the recursion accidentally uses fft:
fft(signalEVEN,lenght/2, power+1);
fft(signalODD,lenght/2, power+1);
Change those to ifft.
The calloc calls do not need this much space:
calloc((lenght/2 + 1), sizeof(double complex));
That can be:
calloc((lenght/2), sizeof(double complex));
Also, the proper spelling of is “length”.
With those fixed, the fft and ifft routines appear to work for some superficial cases.
Related
I am successful in identifying prime and composite from an array. But my qsort function seem to not have any effect when I print the output. I need the primes to be ascending and composite to be descending. When I run the code, it does not sort the output, though it identifies primes and composites.
#include <stdio.h>
#include <stdlib.h>
int compare_Asc(const void *a_void, const void *b_void) {
int a = *(int *)a_void;
int b = *(int *)b_void;
return a - b;
}
int compare_Desc(const void *a_void, const void *b_void) {
int a = *(int *)a_void;
int b = *(int *)b_void;
return b - a;
}
int main() {
int i = 0, n, x, p, c, z, w, j = 0, k = 0, cmpst, null;
int prm;
int prime[50], composite[50], input[50];
printf("How many inputs are you be working with?\nNote: 50 Maximum Inputs\n");
scanf("%d", &n);
printf("Enter the numbers.\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &input[i]);;
}
for (i = 0; i < n; i++) {
if (input[i] % 2 != 0) {
prime[p++] = input[i];
prm = p;
} else
if (input[i] >= 2 && input[i] % 2 == 0) {
composite[c++] = input[i];
cmpst = c;
}
}
printf("Prime Numbers:");
qsort(prime, prm, sizeof(int), compare_Asc);
for (i = 0; i < p; i++) {
printf("%d", prime[p]);
}
printf("Composite Numbers:");
qsort(composite, cmpst, sizeof(int), compare_Desc);
for (i = 0; i < c; i++) {
printf("%d", composite[c]);
}
return 0;
}
There are some major issues, in the posted code, worth mentioning.
Variables
Declaring all the variables at the beginning of the scope, instead of just before where they are used, can hide bugs.
Uninitialized variables, are an even worse source of errors, because their values are indeterminated.
int i=0, n, x, p, c, z, w, j=0, k=0, cmpst, null;
// ^ ^ ^^^^ ?
// ... Later, in the code:
prime[p++] = input[i];
// ^^^ What value is incremented?
// Where is [p++]? Is it inside the prime array?
A correct initialization would prevent undefined behavior.
int p = 0, c = 0;
int composite[50], input[50];
for(int i = 0; i < n ; ++i) {
if ( is_prime(input[i]) ) { // <-- More on this, later.
prime[p++] = input[i];
}
else {
composite[c++] = input[i];
}
}
Loops
This happens a couple of times, just because the code itself is duplicated (another code smell):
for(i=0;i<p;i++){
// ^^^^^^^^^^^ We want to iterate over [0, p).
printf("%d",prime[p]);
// ^ But this always prints the element one past the end
}
Even if it's just a simple loop, it could be a good idea to write a (testable and reusable) function
void print_arr(size_t n, int arr[n])
{
for (size_t i = 0; i < n; ++i) {
printf("%d ", arr[i]);
} // ^
putchar('\n');
}
// ... Later, in main:
print_arr(p, prime);
print_arr(c, composite);
Primes or composite
I am successful in identifying prime and composite from an array
Well, no. Not with this code, I'm sorry.
if (input[i]%2 != 0) { // Those are ALL the ODD numbers!
prime[p++]=input[i];
}
else if(input[i]>=2 && input[i]%2==0){ // Those are the EVEN numbers greater than 0
composite[c++]=input[i];
}
// What about 0 and the even numbers less than 0?
Not all the odd numbers are prime number (it's a little more complicated than that) and 2 itself is a prime, not a composite.
It's unclear to me if this is a terminology issue or if the snippet is only a placeholder for a proper algorithm. In any case, there are multiple examples of primality test functions in SE sites (I'm quite confident some are posted almost every day).
Overflow risk
See chux - Reinstate Monica's comment:
return a-b; risks overflow when a, b are large int values.
Consider return (a > b) - (a < b); for a full range solution.
Single letter variables names are to be avoided... except for i, j and k used in for() loops only.
You're not updating the index of the arrays c and p as the numbers are being printed out. The arrays are being sorted fine.
In the code below I also remove redundant variables, and rename n to input_count, c to compo_count and p to prime_count.
#include <stdio.h>
#include <stdlib.h>
int compare_Asc(const void *a_void, const void *b_void)
{
int a = *(int *) a_void;
int b = *(int *) b_void;
return a - b;
}
int compare_Desc(const void *a_void, const void *b_void)
{
int a = *(int *) a_void;
int b = *(int *) b_void;
return b - a;
}
int main ()
{
int i = 0;
int input_count = 0;
int prime_count = 0;
int compo_count = 0;
int prime[50];
int composite[50];
int input[50];
printf("How many inputs are you be working with?\nNote: 50 Maximum Inputs\n");
scanf("%d", &input_count);
printf("Enter the %d numbers.\n", input_count);
for (i = 0; i < input_count; i++)
{
scanf("%d", &input[i]);
}
for (i = 0; i < input_count; i++)
{
if (input[i] % 2 != 0)
{
prime[prime_count] = input[i];
prime_count += 1;
}
else if (input[i] >= 2 && input[i] % 2 == 0)
{
composite[compo_count] = input[i];
compo_count += 1;
}
}
printf("Prime Numbers:");
qsort(prime, prime_count, sizeof(int), compare_Asc);
for (i = 0; i < prime_count; i++)
{
printf("%d ", prime[i]); // <<-- HERE, not [p]
}
printf( "\n" );
printf ("Composite Numbers:");
qsort(composite, compo_count, sizeof(int), compare_Desc);
for (i = 0; i < compo_count; i++)
{
printf("%d", composite[i]); // <<-- HERE, not [c]
}
printf( "\n" );
return 0;
}
This question already has answers here:
Why do I get a segfault in C from declaring a large array on the stack?
(5 answers)
Closed 3 years ago.
I am learning C and trying new things to test what I can do. I have written code which produces a Mandelbrot set with a given resolution (RES) which is #define RES in the .h file. This works and produces good output for resolutions less than 321. For some reason when RES > 321 then the code no longer executes.
I am running using GCC and plotting the output using Gnuplot. I have tried debugging with a debugger however for RES > 321 the main function no longer gets run? I have added a print in the first line of main() to see and this doesn't get run. An executable is made and the program compiles with no errors?
#include <stdio.h>
#include <math.h>
#define MAX_DEPTH 100
#define RES 321
typedef struct complex_t {
double re;
double im;
} complex;
void init_complex_grid(complex complex_grid[RES][RES], double left, double right, double top, double bottom);
int converge(complex a);
complex add_complex(complex a, complex b);
complex square_complex(complex a);
double mag_complex(complex a);
void output_grid(unsigned int grid[RES][RES]);
int main(void) {
// printf("HERE\n");
int i, j;
unsigned int convergence_grid[RES][RES];
complex complex_grid[RES][RES];
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
return 0;
}
void init_complex_grid(complex complex_grid[RES][RES],
double left, double right,
double top, double bottom) {
int i, j;
double restep = (top - bottom) / RES;
double imstep = (right - left) / RES;
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
complex_grid[i][j].re = left + j * imstep;
complex_grid[i][j].im = bottom + i * restep;
}
}
}
int converge(complex a) {
complex z = { 0, 0 };
int cnt = 0;
while (cnt <= MAX_DEPTH && mag_complex(z) <= 2) {
z = add_complex(square_complex(z), a);
cnt++;
}
return cnt;
}
complex add_complex(complex a, complex b) {
complex added = { a.re + b.re, a.im + b.im };
return added;
}
complex square_complex(complex a) {
complex b;
b.re = a.re * a.re - a.im * a.im;
b.im = 2 * a.re * b.im;
return b;
}
double mag_complex(complex a) {
return sqrt(a.re * a.re + a.im * a.im);
}
void output_grid(unsigned int grid[RES][RES]) {
FILE *f = fopen("mandelbrot.dat", "w");
int i, j;
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
fprintf(f, "%d ", grid[i][j]);
}
fprintf(f, "\n");
}
fclose(f);
printf("\nFILE CLOSED\n");
}
I also added the line printf("\nFILE CLOSED\n"); so I would know that the output had been written to the file but this does not get run either with RES > 321.
You are defining too much data with automatic storage in the main() function: either make the large arrays global, static or allocate them from the heap.
Here is a simple fix you can try:
int main(void) {
int i, j;
static unsigned int convergence_grid[RES][RES];
static complex complex_grid[RES][RES];
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
return 0;
}
Here is an alternative using heap allocation:
int main(void) {
int i, j;
unsigned int (*convergence_grid)[RES] = calloc(sizeof(*convergence_grid), RES);
complex (*complex_grid)[RES] = calloc(sizeof(*complex_grid), RES);
if (!convergence_grid || !complex_grid) {
fprintf(stderr, "cannot allocate arrays\n");
return 1;
}
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
free(complex_grid);
free(convergence_grid);
return 0;
}
I'm a French student and trying to calculate the execution time of the Merge Sort algorithm for different size of array.
I also want to write the different execution time in a .csv file. But when my program tries to sort an array with 1 million elements the process returns -1073741571 (0xC00000FD) in Code::Blocks. So if you could point me to a way to find a solution I would be very grateful!
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void genTab(int *tab, int n) {
int i;
for (i = 0; i < n; i++) {
tab[i] = rand() % 100;
}
}
void fusion(int *tab, int deb, int mid, int fin) {
int i = deb;
int j = mid + 1;
int k = deb;
int temp[fin + 1];
while ((i <= mid) && (j <= fin)) {
if (tab[i] <= tab[j]) {
temp[k] = tab[i];
i++;
} else {
temp[k] = tab[j];
j++;
}
k++;
}
while (i <= mid) {
temp[k] = tab[i];
i++;
k++;
}
while (j <= fin) {
temp[k] = tab[j];
k++;
j++;
}
for (i = deb; i <= fin; i++) {
tab[i] = temp[i];
}
}
void triFusion(int *tab, int i, int j) {
if (i < j) {
triFusion(tab, i, (int)((i + j) / 2));
triFusion(tab, (int)((i + j) / 2 + 1), j);
fusion(tab, i, (int)((i + j) / 2), j);
}
}
void reset(int *tab1, int *tab2, int n) {
for (int i = 0; i < n; i++) {
tab2[i] = tab1[i];
}
}
int main() {
srand(time(NULL));
clock_t start, end;
int nbrTest[15] = {
1000, 5000, 10000, 50000, 80000, 100000, 120000, 140000,
150000, 180000, 200000, 250000, 300000, 450000, 1000000
};
FILE *fp;
char *tpsExecution = "exeTime.csv";
fp = fopen(tpsExecution, "w");
fprintf(fp, "Array Size; Merge Time");
for (int i = 0; i < 15; i++) {
int n = nbrTest[i];
printf("Calculating time for an array of %d \n", n);
int *tab = malloc(sizeof(int) * n);
genTab(tab, n);
int *copie = malloc(sizeof(int) * n);
reset(tab, copie, n);
start = clock();
triFusion(tab, 0, n - 1);
end = clock();
float tpsFusion = (float)(end - start) / CLOCKS_PER_SEC;
reset(tab, copie, n);
printf("writing in the file\n");
fprintf(fp, "\n%d;%f", n, tpsFusion);
free(tab);
free(copie);
}
fclose(fp);
return 0;
}
int temp[fin+1]; may exceed the space limit for the stack. You should allocate it with malloc instead, and free it with free.
If you want to exclude malloc and free from the timed code, the allocation could be performed outside the timed code and passed in as work space.
(Note: posted after the answer from #Eric Postpischil).
The function
void fusion(int * tab, int deb, int mid, int fin)
Has the line
int temp[fin+1];
and the value of fin comes through another function from the number of elements n to be sorted
triFusion(tab, 0, n-1);
and as an automatic variable, breaks the stack when n is large.
I suggest replacing the line with
int *temp = malloc((fin+1) * sizeof *temp);
if(temp == NULL) {
puts("malloc");
exit(1);
}
// ...
free(temp);
fusion() is always allocating the full size of the array for temp, even when only a small fraction of temp is being used. You could change this to:
int k = 0;
...
int temp[fin+1-deb];
...
tab[i]=temp[i-deb];
still this will exceed stack space if n is large. So as suggested in the other answers:
int k = 0;
...
int *temp = malloc((fin+1-deb)*sizeof(int));
...
tab[i]=temp[i-deb];
...
free(temp)
or better still, do a one time allocation of a second array in main or in a "helper" function, the include a pointer to the second array in the merge sort functions.
All the solutions I have seen online has calloc() function used twice, is it possible to do with only using it once?
The below code is not printing the correct array elements
int **ptr;
//To allocate the memory
ptr=(int **)calloc(n,sizeof(int)*m);
printf("\nEnter the elments: ");
//To access the memory
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",ptr[i][j]);
}
}
Since C99 you can use pointers to VLAs (Variable Length Arrays):
int n, m;
scanf("%d %d", &n, &m);
int (*ptr)[m] = malloc(sizeof(int [n][m]));
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &ptr[i][j]); // Notice the address of operator (&) for scanf
}
}
free(ptr); // Call free only once
If it's just about minimising the number of calls to memory allocation functions you can created such a jagged array like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t n, size_t m)
{
int ** result = NULL;
size_t t = 0;
t += n * sizeof *result;
t += n*m * sizeof **result;
result = calloc(1, t);
if (NULL != result)
{
for (size_t i = 0; i < n; ++i)
{
result[i] = ((int*) (result + n)) + i*m;
}
}
return result;
}
Use it like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t, size_t);
int main(void)
{
int result = EXIT_SUCCESS;
int ** p = alloc_jagged_2d_array_of_int(2, 3);
if (NULL == p)
{
perror("alloc_jagged_2d_array_of_int() failed");
result = EXIT_FAILURE;
}
else
{
for (size_t i = 0; i < 2; ++i)
{
for (size_t j = 0; j < 3; ++j)
{
p[i][j] = (int) (i*j);
}
}
}
/* Clean up. */
free(p);
return result;
}
I'm having an issue with compling the code.
I keep getting these errors.
"C: 194 warning passing argument 3 of 'matrix_column_subtract' makes pointer from integer without a cast"
"C: 12 note: expected 'double**' but argument is type 'int'
"C: 194 error too few arguments to function 'matrix_column_subtract'
I think I know what is going on I'm calling matrix_column_multiply is a void and I need to be calling it a pointer pointer I think and I don't know how to chage that. If anyone has some idea on how I can get this to compile that would be highly appreciated!!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define DEBUG 0
#define MAX_ITER 10000
double *eigen (int n, double **A);
void qr_decomp (int n, double **A, double **Q, double **R);
void matrix_copy_column(double **msrc, int col1, double **mdst,int col2, int rows);
void matrix_column_subtract(double **m1, int c1, double **m2, int c2, int rows);
void matrix_column_multiply(double **m, int c, double k, int rows);
int main() {
int i, n = 126;
double *eig, **Am;
FILE *BinInp, *TxtOut;
/* Input Code: Reads bv, Am in binary form from CGrad.bin */
if ( (BinInp = fopen("CGrad.bin","r")) == NULL ) {
fprintf(stderr, "Cannot open matrix binary file INPUT... exiting\n");
exit(-1);
}
Am = (double**)malloc (n*sizeof(double*));
Am[0] = (double*)malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Am[i] = Am[0] + i*n;
}
for (i = 0; i < n; i++) {
if (i==0) { /* Read one extra line that is discarded (bv is still in bin file) */
if (!fread(Am[i], sizeof(double), n, BinInp)) {
fprintf(stderr, "Cannot read row Am[%03d] of matrix... exiting\n", i+1);
exit(1);
}
}
if (!fread(Am[i], sizeof(double), n, BinInp)) {
fprintf(stderr, "Cannot read row Am[%03d] of matrix... exiting\n", i+1);
exit(1);
}
}
if (fclose(BinInp) == EOF) {
fprintf(stderr, "Cannot close matrix binary file INPUT... exiting\n");
exit(-1);
}
/* COMPUTE EIGENVALUES HERE USING FUNCTIONS. RETURN EIGENVALUES (AS 1D VECTOR) TO eig. */
if (DEBUG) printf ("Calling eigen\n");
eig = eigen (n, Am);
/* Output Code: Writes eig in text form to Eigs.txt */
if ( (TxtOut = fopen("Eigs.txt", "w")) == NULL ) {
fprintf(stderr, "Cannot open matrix text file OUTPUT... exiting\n");
exit(-1);
}
for (i = 0; i < n; i++) {
fprintf (TxtOut, "%18.14e ", eig[i]);
}
if (fclose(TxtOut) == EOF) {
fprintf(stderr, "Cannot close matrix text file INPUT... exiting\n");
exit(-1);
}
return 0;
}
double* eigen (int n, double **Acur)
{
double err = 1, eps = 1e-2;
double ndenom, nnumer, temp;
double *eig, **Anex, **Qsub, **Rsub;
int i, j, k, iters = 1;
/* Malloc memory for the three matricies */
Anex = malloc (n*sizeof(double*));
Anex[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Anex[i] = Anex[0] + i*n;
}
Qsub = malloc (n*sizeof(double*));
Qsub[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Qsub[i] = Qsub[0] + i*n;
}
Rsub = malloc (n*sizeof(double*));
Rsub[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Rsub[i] = Rsub[0] + i*n;
}
/* Malloc memory for the return eig vector */
eig = malloc (n*sizeof(double));
for (i = 0; i < n; i++) {
eig[i] = 0;
}
/* Enter main iteration loop for eigenvalues */
while (err > eps && iters < MAX_ITER) {
/* QR Decompose Acur then find next iterate value in Anex */
qr_decomp (n, Acur, Qsub, Rsub);
// FIND NEXT ITERATE VALUE, PUT IN Anex.
/* Determine relative error change, reset "old" iterate value. */
ndenom = 0;
nnumer = 0;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
temp = Anex[i][j]-Acur[i][j];
ndenom += temp*temp;
nnumer += Anex[i][j]*Anex[i][j];
Acur[i][j] = Anex[i][j];
}
}
err = sqrt(ndenom)/sqrt(nnumer);
/* Increment the iteration count and report error */
if (iters % 25 == 0) {
printf ("Error at end of iteration %05d = %14.10f %%\n", iters, 100*err);
}
++iters;
}
printf ("Error at end of iteration %05d = %14.10f\nCONVERGED.\n", iters-1, err);
if (iters == MAX_ITER) {
printf ("WARNING: MAX_ITER iterations reached!...\n");
}
/* Copy diagonal entries of Acur into eig for return to main */
for (i=0; i<n; i++) {
eig[i] = Acur[i][i];
}
return eig;
}
void qr_decomp (int n, double **Adec, double **myQ, double **myR)
{
int i, j, k; /* Loop Variables: this is all you should need! */
double **T, **S;
double r;
T = malloc (n*sizeof(double*));
T[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
T[i] = T[0] + i*n;
}
S = malloc (n*sizeof(double*));
S[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
S[i] = S[0] + i*n;
}
/* Main loop for decomposition */
for (i=0; i<n; i++) {
/* Column i of Q is initially column i of A */
matrix_copy_column(Adec,i,myQ,i,n);
/* For j < i-1, Perform the dot product between the j row of Q and the
i row of A to determine the R(j,i) value, then insure the Q i column
is orthogonal to all other Q columns by subtracting existing Q columns
from it. */
for (j = 0; j < i; j++) {
//r[j,i] = Qj^T * Ui
matrix_copy_column(myQ,j,T,0,n);
matrix_copy_column(Adec,i,S,0,n);
for (k=0; k<n; k++) {
r += T[k][0] * S[k][0];
}
/* Determine the R diagonal as the magnitude of the Q column, then
normalize the Q column (make it a unit vector). */
//Qi = Ui
myR[j][i] = r;
// Something wrong here.
// There is one parameter missing, as matrix_column_subtract needs 5 parameters and
// only 4 are given.
// Also, matrix_column_multiply is defined as returning a void, whereas the 3rd parameter
// of matrix_column_subtract should be a double **
matrix_column_subtract(myQ,i,matrix_column_multiply(T,0,r,n),j);
}
}
}
/* Copies a matrix column from msrc at column col1 to mdst at column col2 */
void matrix_copy_column(double **msrc, int col1, double **mdst,int col2, int rows) {
int i = 0;
for (i=0; i<rows; i++) {
mdst[i][col2] = msrc[i][col1];
}
}
/* Subtracts m2's column c2 from m1's column c1 */
void matrix_column_subtract(double **m1, int c1, double **m2, int c2, int rows) {
int i = 0;
for (i=0; i<rows; i++) {
m1[i][c1] -= m2[i][c2];
}
/*return m1;*/
}
void matrix_column_multiply(double **m, int c, double k, int rows) {
int i = 0;
for (i=0; i<rows; i++) {
m[i][c] *= k;
}
/*return m;*/
}
A problem is here.
matrix_column_subtract(myQ,i,matrix_column_multiply(T,0,r,n),j);
The relevant function signatures are:
void matrix_column_subtract(double **m1, int c1, double **m2, int c2, int rows);
void matrix_column_multiply(double **m, int c, double k, int rows);
Note that matrix_column_multiply returns void, but you're passing it in as if it were double **. I'm guessing the compiler is desperately trying to make it work and returned some sort of garbage integer.
These functions return void because they do their work directly on the matrix in question. matrix_column_multiply alters m. matrix_column_subtract alters m1.
To make it work, call matrix_column_multiply on T then pass T (now modified by the multiplication) into matrix_column_subtract.
matrix_column_multiply(T, 0, r, n);
matrix_column_subtract(myQ, i, T, j, ...rows...);
You're still missing the fifth argument, rows. I'm going to guess that's n, same as has been used for the rows in every other matrix_column_blah call.