how to numerically integrate a variable that is being calculate in the program as a pointer (using e.g. trapezoidal rule) in c language - c

I have a code, that was not made by me.
In this complex code, many rules are being applied to calculate a quantity, d(x). in the code is being used a pointer to calculate it.
I want to calculate an integral over this, like:
W= Int_0 ^L d(x) dx ?
I am doing this:
#define DX 0.003
void WORK(double *d, double *W)
{
double INTE5=0.0;
int N_X_POINTS=333;
double h=((d[N_X_POINTS]-d[0])/N_X_POINTS);
W[0]=W[0]+((h/2)*(d[1]+2.0*d[0]+d[N_X_POINTS-1])); /*BC*/
for (i=1;i<N_X_POINTS-1;i++)
{
W[i]=W[i]+((h/2)*(d[0]+2*d[i]+d[N_X_POINTS]))*DX;
INTE5+=W[i];
}
W[N_X_POINTS-1]=W[N_X_POINTS-1]+((h/2)*(d[0]+2.0*d[N_X_POINTS-1]+d[N_X_POINTS-2])); /*BC*/
}
And I am getting "Segmentation fault". I was wondering to know if, I am doing right in calculate W as a pointer, or should declare it as a simple double? I guess the Segmentation fault is coming for this.
Other point, am I using correctly the trapezoidal rule?
Any help/tip, will very much appreciate.
Luiz

I don't know where that code come from, but it is a lot ugly and has some limits hard-encoded (333 points and increment by 0.003). To use it you need to "sample" properly your function and generate pairs (x, f(x))...
A possible clearer solution to your problem is here.
Let us consider you function and let us suppose it works (I believe it does't, it's a really obscure code...; e.g. when you integrate a function, you expect a number as result; where's this number? Maybe INTE5? It is not given back... and if it is so, why the final update of the W array? It's useless, or maybe we have something meaningful into W?). How does would you use it?
The prototype
void WORK(double *d, double *W);
means the WORK wants two pointers. What these pointers must be depends on the code; a look at it suggests that indeed you need two arrays, with N_X_POINTS elements each. The code reads from and writes into array W, and reads only from d. The N_X_POINTS int is 333, so you need to pass to the function arrays of at least 333 doubles:
double d[333];
double W[333];
Then you have to fill them properly. I thought you need to fill them with (x, f(x)), sampling the function with a proper step. But of course this makes no too much sense. Already said that the code is obscure (now I don't want to try to reverse engineering the intention of the coder...).
Anyway, if you call it with WORK(d, W), you won't get seg fault, since the arrays are big enough. The result will be wrong, but this is harder to track (again, sorry, no "reverse engineering" for it).
Final note (from comments too): if you have double a[N], then a has type double *.

A segmentation fault error often happens in C when you try to access some part of memory that you shouldn't be accessing. I suspect that the expression d[N_X_POINTS] is the culprit (because arrays in C are zero-indexed), but without seeing the definition of d I can't be sure.
Try putting informative printf debugging statements before/after each line of code in your function so you can narrow down the possible sources of the problem.

Here's a simple program that integrates $f(x) = x^2$ over the range [0..10]. It should send you in the right direction.
#include <stdio.h>
#include <stdlib.h>
double int_trapezium(double f[], double dX, int n)
{
int i;
double sum;
sum = (f[0] + f[n-1])/2.0;
for (i = 1; i < n-1; i++)
sum += f[i];
return dX*sum;
}
#define N 1000
int main()
{
int i;
double x;
double from = 0.0;
double to = 10.0;
double dX = (to-from)/(N-1);
double *f = malloc(N*sizeof(*f));
for (i=0; i<N; i++)
{
x = from + i*dX*(to-from);
f[i] = x*x;
}
printf("%f\n", int_trapezium(f, dX, N));
free(f);
return 0;
}

Related

why does it show segmentation fault when I tried to use recursion here?

I tried to write a code to calculate how many 1 are there in a number's binary form. This is my code:
#include <stdio.h>
#include <math.h>
static int num = 0;
void binary(int target){
int n = 0;
int a = 1;
if(target != 0){
while(target >= a ){
n++;
a = pow(2, n);
}
a = pow(2, n-1);
num++;
binary(target - a);
}
}
int main() {
int target = 0;
scanf("%d", &target);
binary(target);
printf("%d",num);
return 0;
}
However, this shows segmentation fault when I run it. I don't know where has the code tried to access memories that are not allowed. I figured it might have something to do with the recursion in the binary function. Can anyone tell me what have caused the segmentation fault here? Thank you so much. I really can't understand segfaults :(
As mentioned in the comments, pow is not a good candiate here due to its signature:
double pow(double x, double y);
so any place that you are using pow, you are implicitly using floating point numbers. I was able to cause a segfault with the input 1<<31 which is the value -2147483648. This will cause your loop to terminate with n=0, a=1. You then set a = pow(2, -1), but since a is an integer, this gets floored down to just 0. You then recurse with binary(target - 0) which might as well just be binary(target) again, hence you have an infinite call with no termination.
I'll also leave as a note that recursion for this type of problem is probably not the right tool, unless your goal is to learn about recursion. There is a much more concise and reliable method via a loop and the & operator. I would also suggest using unsigned values to avoid issues like this with negative terms.

How would I go about converting these equations to C code?

I have these two equations
and I need to convert them to C code where you inputk and x. The thing is I don't get that advanced levels of math, neither did I learn C in the past :D
Can anyone show me step by step what built-in functions can be used for this and how exactly should the logic behind the app work?
Cheers!
Your formula is wrong. As shown here (along with the proof of the derivation) the correct formula is
You have k and n swapped in your summation. The inputs should then be x and n. The correct code is then:
#include <math.h>
double sum_of_sin(double x, int n) {
if (sin(x/2) == 0.0) {
return 0.0; //prevent division by 0 for x multiple of 2π
}
return sin(n*x/2) * sin((n+1)*x/2) / sin(x/2);
}
You can include the file math.h which has inbuilt functions like cos() and sin().
For instance:
#include <stdio.h>
#include <math.h>
int main ()
{
double res;
ret = cos(45);
printf("The cos of angle 45 is %f",res);
return 0;
}
Hope it helps..
You have an equation that consists of two formulae. It is easy to write the two parts out, but it can be hard to find a solution. The right-hand part of the first formula would be:
float RHvalue;
RHvalue = (sin( ((n+1.0)*x) / 2.0 ) * sin(n * x/2.0) ) / sin(x/2.0);
now, what the values of kx would be, is another matter, though it would be easy to sum them.

strange daxpy Fortran in c

I'm still fairly new to c and i can't seem to understand this small bit of code.
void daxpy(int N, double alpha, double *x, double *y)
y=alpha*x+y
for (i=0, i<N, i++)
y[1]=alpha*x[1]+y[1];
i don't seem to know what daxpy function is doing or even its purpose. I know its probably something not very difficult. any help will be much appreciated. this was on my notes. I was just curious about what it was. I know the obvious things like daxpy is a function call. but just need a small explanation on it
I would think the actual code is like this:
void daxpy(int N, double alpha, double *x, double *y)
{
for (int i = 0, i < N, i++)
y[i]= alpha * x[i] + y[i];
}
This is because when looking at your code y = alpha * x + y does not seem to make sense. As x and y seems to be array, it should not work that way.
Furthermore, the following code is a loop, which I would think it explains the statement of y = alpha * x + y itself. And the number in the indices should be i instead of 1, because it is a loop from 0 to N. It does not make sense to put 1 there.
So that function call is basically just to add every element of array y with it's corresponding value in x multiplied by a constant alpha.

Multiply each element of an array by a number in C

I'm trying to optimize some of my code in C, which is a lot bigger than the snippet below. Coming from Python, I wonder whether you can simply multiply an entire array by a number like I do below.
Evidently, it does not work the way I do it below. Is there any other way that achieves the same thing, or do I have to step through the entire array as in the for loop?
void main()
{
int i;
float data[] = {1.,2.,3.,4.,5.};
//this fails
data *= 5.0;
//this works
for(i = 0; i < 5; i++) data[i] *= 5.0;
}
There is no short-cut you have to step through each element of the array.
Note however that in your example, you may achieve a speedup by using int rather than float for both your data and multiplier.
If you want to, you can do what you want through BLAS, Basic Linear Algebra Subprograms, which is optimised. This is not in the C standard, it is a package which you have to install yourself.
Sample code to achieve what you want:
#include <stdio.h>
#include <stdlib.h>
#include <cblas.h>
int main () {
int limit =10;
float *a = calloc( limit, sizeof(float));
for ( int i = 0; i < limit ; i++){
a[i] = i;
}
cblas_sscal( limit , 0.5f, a, 1);
for ( int i = 0; i < limit ; i++){
printf("%3f, " , a[i]);
}
printf("\n");
}
The names of the functions is not obvious, but reading the guidelines you might start to guess what BLAS functions does. sscal() can be split into s for single precision and scal for scale, which means that this function works on floats. The same function for double precision is called dscal().
If you need to scale a vector with a constant and adding it to another, BLAS got a function for that too:
saxpy()
s a x p y
float a*x + y
y[i] += a*x
As you might guess there is a daxpy() too which works on doubles.
I'm afraid that, in C, you will have to use for(i = 0; i < 5; i++) data[i] *= 5.0;.
Python allows for so many more "shortcuts"; however, in C, you have to access each element and then manipulate those values.
Using the for-loop would be the shortest way to accomplish what you're trying to do to the array.
EDIT: If you have a large amount of data, there are more efficient (in terms of running time) ways to multiply 5 to each value. Check out loop tiling, for example.
data *= 5.0;
Here data is address of array which is constant.
if you want to multiply the first value in that array then use * operator as below.
*data *= 5.0;

Converting from log to linear in C and taking average

I don't know C well at all, and I'm trying to edit someone's code, but I'm having issues when trying to convert values from the log to linear domains.
For example, let's say we have an array A that is full of log values equal to -100 dB, i.e.
float A[100];
int i;
for( i=0; i<100; i++ )
A[i] = -100;
What I want to do is find the average of all the values (which clearly is -100), but by taking the average in the linear and not log domain, i.e.
float tmp_avg = 0.0;
float avg;
int count = 0;
for( i=0; i<100; i++ ) {
tmp_avg += pow(10.0, A[i]/10.0);
count++;
}
avg = 10*log10(tmp_avg / count);
However, the result I'm getting is all 0's. Now the code I'm working on is much more complex than this, but I was wondering if there's anything obvious that I'm missing as to why this won't work.
One thought I had is that 10^(-100/10) is a very small value (1e-10), and perhaps too small to be accurately defined as a float. I've tried making it a double instead, but I still get a result of all 0's.
Thanks!
Just figured out what the problem was: I needed to include the math.h library at the top of the program:
#include <math.h>
Without that, I believe that there was no reference for the log10 function, which in turn caused the result to be all 0's. I now include math.h and everything seems to be working fine.

Resources