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.
Related
I'm writing a program that calculates the value of the normal distribution function given to me here:
The program is supposed to ask the user for the mean μ and the Standard Deviation σ for the normal distribution showed above. The program then asks for N values of x and then asks for each value of x, one by one. After each value x it writes out the corresponding value of the function.
This is my code so far:
#define _USE_MATH_DEFINES
#include <stdio.h>
#include <math.h>
int main() {
int j;
double u, stddev, N, result, x;
printf("Enter u and stddev for the Normal Distribution:\n");
scanf("%lf %lf",&u, &stddev);
printf("Enter how many values of x (N) for the Normal Distribution:\n");
scanf("%lf",&N);
for (j=0; j<N; j++) {
printf("Enter a value for x: \n");
scanf("%lf",&x);
result = ((1)/(stddev*sqrt(2*M_PI)))*exp(-(1/2)*((x-u)/stddev)*((x-u)/stddev));
printf("%.6lf\n", result);
}
}
I'm basically done but the answers the program is giving me are wrong when compared to my answers from my calculator. For instance, when I make N = 3 no matter what I put for the 3 values of x, the answer it gives me for each are the same when they shouldn't be.
So I know my issue lies in this line of code:
result = ((1)/(stddev*sqrt(2*M_PI)))*exp(-(1/2)*((x-u)/stddev)*((x-u)/stddev));
Am I just writing the function wrong in the program? I must be, for it not to work.
Your code is clean and functional. Good work so far.
You were correct about which line needed changing - The issue is that using integer division results in an integer, so 1 / 2 results in a value of 0. This can be remedied by using a single double value: 0.5, or by dividing using doubles 1.0 / 2.0.
result = ((1)/(stddev*sqrt(2*M_PI)))*exp(-(0.5)*((x-u)/stddev)*((x-u)/stddev));
I tested out your code after making these changes try it online, and they match up perfectly with the formula on wolfram alpha, as well as what you said in the comments.
For example:
μ=2, σ=3, x=7 results in 0.033159
μ=3, σ=7, x=0 results in 0.051991
μ=4, σ=4, x=4 results in 0.099736
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;
I am writing a program that reads wavelength and intensity data from separate signal and background files (so each file is comprised of a number of pairs of wavelength and intensity). As you can see, I do this by creating a structure, and then assigning the values to the proper elements in the structure using fscanf in a loop. Once the data is read in, the program is supposed to plot it on the interval where the recorded wavelengths in each file overlap, that is, the common range of wavelengths. The wavelengths align perfectly where this overlap exist and are known to be spaced at a constant difference. Thus, my way of discerning which elements of the structure array were applicable was to determine which of the two files' minimum wavelength was higher, and maximum wavelength was lower. Then, for the file that had the lower minimum and higher maximum, I would find the difference between this and the higher minimum/lower maximum, and then divide it by the constant step to determine how many elements to offset. This works, except when the math is done, the program returns a wrong answer that is completely inexplicable.
In the code below, I define the constant step as lambdastep by calculating the difference between wavelengths of one element and the element before it. With my sample data, it is .002, which is confirmed by printf. However, when I run the program and divide by lambdastep, I get an incorrect answer. When I run the program dividing by .002, I get the correct answer. Why is this case? There is no explanation I can think of.
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include "plots.h"
struct spectrum{
double lambda;
double intensity;
};
main(){
double a=0,b=0,c=0,d=0,lambdastep,smin,smax,bmin,bmax,tmin,tmax,sintmin,bintmin,tintmin,sintmax,bintmax,tintmax,ymin,ymax;
int ns,nb,nt,i=0,sminel,smaxel,bminel,bmaxel,tminel,tmaxel;
double min(struct spectrum *a,int,int);
double max(struct spectrum *a,int,int);
FILE *Input;
Input = fopen("sig.dat","r");
FILE *InputII;
InputII = fopen("bck.dat","r");
fscanf(Input,"%d",&ns);
fscanf(InputII,"%d",&nb);
struct spectrum signal[ns];
struct spectrum background[nb];
struct spectrum *s = &signal[0];
struct spectrum *ba = &background[0];
s = malloc(ns*sizeof(struct spectrum));
ba = malloc(nb*sizeof(struct spectrum));
while( fscanf(Input,"%lf%lf",&a,&b) != EOF){
signal[i].lambda = a;
signal[i].intensity = b;
i++;
}
i = 0;
while( fscanf(InputII,"%lf%lf",&c,&d) != EOF){
background[i].lambda = c;
background[i].intensity = d;
i++;
}
for (i=0; i < ns ;i++){
printf("%.7lf %.7lf\n", signal[i].lambda,signal[i].intensity);
}
printf("\n");
for (i=0; i < nb ;i++){
printf("%.7lf %.7lf\n", background[i].lambda,background[i].intensity);
}
lambdastep = signal[1].lambda - signal[0].lambda; //this is where I define lambdastep as the interval between two measurements
smin = signal[0].lambda;
smax = signal[ns-1].lambda;
bmin = background[0].lambda;
bmax = background[nb-1].lambda;
if (smin > bmin)
tmin = smin;
else
tmin = bmin;
if (smax > bmax)
tmax = bmax;
else
tmax = smax;
printf("%lf %lf %lf %lf %lf %lf %lf\n",lambdastep,smin,smax,bmin,bmax,tmin,tmax); //here is where I confirm that it is .002, which is the expected value
sminel = (tmin-smin)/(lambdastep); //sminel should be 27, but it returns 26 when lamdastep is used. it works right when .002 is directly entered , but not with lambdastep, even though i already confirmed they are exactly the same. why?
sminel is an integer, so (tmin-smin)/lambdastep will be casted to an integer when the calculation concludes.
A very slight difference in lambdastep could be the difference between getting e.g. 27.00001 and 26.99999; the latter truncates down to 26 when cast to an int.
Try using floor, ceil, or round to get better control over the rounding of the returned value.
It almost certainly has to do with the inherent imprecision of floating-point calculations. Trying printing out lambdastep to many significant digits -- I bet you'll find that its exact value is slightly larger than you think it is.
With my sample data, it is .002, which is confirmed by printf.
Try printing out (lambdastep == .002).
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;
}
I'm trying to convert a simple numerical analysis code (trapezium rule numerical integration) into something that will run on my CUDA enabled GPU. There is alot of literature out there but it all seems far more complex than what is required here! My current code is:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define N 1000
double function(double);
int main(void)
{
int i;
double lower_bound, upper_bound, h, ans;
printf("Please enter the lower and upper bounds: ");
scanf(" %lf %lf", &lower_bound, &upper_bound);
h = (upper - lower) / N;
ans = (function(lower) + function(upper)) / 2.0;
for (i = 1; i < N; ++i) {
ans += function(i * h);
}
printf("The integral is: %.20lf\n", h * ans));
return 0;
}
double function(double x)
{
return sin(x);
}
This runs well until N becomes very large. I've made an implementation with openMP which is faster but I think it will be handy to know a little about CUDA too. Has anyone got any suggestions about where to start or if there is a painless way to convert this code? Many Thanks, Jack.
It's the loop that would have to be distributed to parallel threads. You can calculate a unique index for each thread (idx = 0...N-1). Each thread merely calculates its individual part of the integral and stores the answer in its position in a common array (intgrl[idx]). You then sum everything up using a procedure called a parallel scan or gather. There are examples in the NVIDIA cuda examples. The easiest way would be to use the Thrust library. You simply tell it "add up these values" and it calculates the fastest method.
You could get rid of the multiplication :D
double nomul = h;
for (i = 1; i < N; ++i) {
ans += function(nomul);
nomul += h;
}
First, go ahead and install CUDA on your computer. After that, try to run some of the examples available on the SDK. They may look a little complicated at first sight, but don't worry, there are tons of CUDA "Hello World" examples on the web.
If you're looking for something fancier, you could try compiling this project (you'll need to install OpenCV), which converts an image to its grayscale representation (it has files to compile on Windows/Linux/Mac OS X, so its worth taking a look if you need help to compile your projects).