segment fault on programming C - c

I am tyring to make velocity Verlet method, by using C language.
I thought I made it good. However, there pops up 'Segmentation fault(core dumped)' whenever, I increase the size of the vector or array, x and y.
For the size n equal and less than 1e3, it's fine, but at the point of n = 1e4, the program gets error.
Please anybody help me on this.
Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double verlet(double t, double x)
{
double E = 0.252;
double B = 0.052;
double a = M_PI/2;
return -sin(x) + E*cos(t) + B*cos(2*t+a);
}
double pverlet(double(*f)(double, double), double dt, double t, double x, double y)
{
return x + dt*( y + (dt/2)*f(t, x));
}
double vverlet(double(*g)(double, double), double dt, double t, double x, double y)
{
return y + (dt/2) * g(t, x);
}
int main(void)
{
int i;
double t;
int n = 1e4;
double ti = 0, tf = 1e5, dt = (tf-ti)/n;
double *x = (double *) malloc(sizeof(double)*n);
double *y = (double *) malloc(sizeof(double)*2*n);
if (x == NULL)
{
printf("error allocating memory!\n");
return 1;
}
if (y == NULL)
{
printf("error allocating memory!\n");
return 1;
}
for (y[0] = 0, i = 1; i <2*n; i++)
{
y[i] = vverlet(verlet, dt, ti + dt*(i-1), x[i-1], y[i-1]);
}
for (x[0] = 0, i = 1; i < n; i++)
{
x[i] = pverlet(verlet, dt, ti + dt*(i-1), x[i-1], y[2*(i-1)]);
}
for (i = 0; i < n; i++)
{
t = ti + dt * i;
printf("%e %e %e\n", t, x[i], y[2*i]);
}
return 0;
free(x);
free(y);
}

for (y[0] = 0, i = 1; i <2*n; i++)
{
y[i] = vverlet(verlet, dt, ti + dt*(i-1), x[i-1], y[i-1]);
}
x is defined from 0 to n-1.

Related

In C returned error: -1073741819 (0xC0000005)

I program in C and I am testing my program and I don't understand why I get the error -1073741819 (0xC0000005). Here is the Code:
#include <stdio.h>
#include <stdlib.h>
double interpol(double x0, double y0, double x1, double y1, double h) {
double ergebnis = (y1 - y0) / (x1 - x0) * h;
printf("%.2f\n", ergebnis);
return ergebnis;
}
void interpol_array(double *x_org, double *y_org, int dim_org,
double *x_int, double *y_int, int dim_int,
int n) {
int j, i;
double h;
i = 0;
y_org[0] = y_int[0];
for (j = 1; j < dim_int; j++) {
if (j % (n + 1) == 0 && j != 0) {
i++;
x_int[j] = x_org[i];
y_int[j] = x_org[i];
continue;
}
printf("%.2f ", y_org[0]);
}
}
int main() {
/* Pointer erzeugen auf null setzen */
double *xArrayOriginal = NULL;
double *yArrayOriginal = NULL;
double *xArrayInterpol = NULL;
double *yArrayInterpol = NULL;
/**/
int dimOriginal = 2;
int n = 3;
int dimInterpol = (n + 1) * (dimOriginal + 1) - n; /*+1 wegen der null*/
int i, j;
double h;
/* Array für die Originalwerte erzeugen */
xArrayOriginal = (double *)malloc(dimOriginal * sizeof(double));
yArrayOriginal = (double *)malloc(dimOriginal * sizeof(double));
/*Array für das Interpolierte Array erzeugen*/
xArrayInterpol = (double *)malloc(dimInterpol * sizeof(double));
yArrayInterpol = (double *)malloc(dimInterpol * sizeof(double));
xArrayOriginal[0] = 0;
xArrayOriginal[1] = 1;
xArrayOriginal[2] = 2;
yArrayOriginal[0] = 2;
yArrayOriginal[1] = 4;
yArrayOriginal[2] = 8;
interpol_array(xArrayOriginal, yArrayOriginal, dimOriginal, xArrayInterpol,
yArrayInterpol, dimInterpol, n);
return 0;
}
In my program I have 4 dynamic arrays. 2 dynamic arrays for origin x and y values and 2 dynamic arrays for interpolated x and y values. I don't program the full interpolation because I got an error. Therefore I searched the error and found out that when I use
printf("%.2f ", y_org[0]);
I get the error that you can see above. Only when I change it to
printf("test");
it works fine. So why do I get this error. what is wrong with my array list?
In the function main, the lines
int dimOriginal = 2;
...
xArrayOriginal =(double *)malloc(dimOriginal*sizeof(double));
yArrayOriginal =(double *)malloc(dimOriginal*sizeof(double));
allocate arrays for 2 double elements each. However, the lines
xArrayOriginal[2] =2;
...
yArrayOriginal[2] =8;
write out of bounds of these arrays, as the only valid elements numbers are 0 and 1. This causes undefined behavior.
Also, in the function interpol_array, the following line causes undefined behavior:
y_org[0] = y_int[0];
This is because y_int has been assigned the value of yArrayInterpol in main, but the contents of yArrayInterpol has not been initialized.

Loop in basic C program

I can't find and resolve the error in this code.
I want Parray and Tarray to be filled with an iteration of the equation in the loop. I tried both for and while loop, but it seems that only the first member of the array is given proper value, and that value is lost by the beginning of a new cycle.
#include <stdio.h>
#include <stdlib.h>
int main() {
int i;
int j;
float dt,P_init,t_init,t_end;
dt = 0.03125;
P_init = 30;
t_init = 0;
t_end = 30;
int n_steps = 0;
n_steps = t_end/(float)dt;
int Parray[n_steps+1];
int Tarray[n_steps+1];
for (i=0; i<n_steps+1; i++)
{
Parray[i]=0;
Tarray[i]=0;
}
Parray[0] = P_init;
Tarray[0] = t_init;
int x;
float P,t,dpdt;
x = 1;
while (x < n_steps+1)
{
float s,d;
P = Parray[x-1];
t = Tarray[x-1];
dpdt = 0.7 * P * (1-(P/750)) - 20;
s = P + (dt * dpdt);
Parray[x] = s;
d = t + dt;
Tarray[x] = d;
x++;
printf("%f %f ",s,d);
}
return(0);
}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i, j, x;
float dt, P_init, t_init, t_end, P, t, dpdt;
dt = 0.03125;
P_init = 30;
t_init = 0;
t_end = 30;
int n_steps = 0;
n_steps = t_end / (float)dt;
// using float arrays
float Parray[n_steps+1];
float Tarray[n_steps+1];
for (i = 0; i < n_steps+1; i++)
Parray[i] = 0;
for (j = 0; j < n_steps+1; j++)
Tarray[j] = 0;
Parray[0] = P_init;
Tarray[0] = t_init;
for (x = 1; x < n_steps + 1; x++) {
float s , d;
P = Parray[x-1];
t = Tarray[x-1];
dpdt = 0.7 * P * (1 - (P / 750)) - 20;
s = P + (dt * dpdt);
Parray[x] = s;
d = t + dt;
Tarray[x] = d;
printf("%f %f\n", s, d);
}
return(0);
}
I changed the int arrarys to float arrays.
What do you actually calculate here?
This line
dpdt = 0.7 * P * (1-(P/750)) - 20;
It seems to have a float value, therefore the array must be float type, and ALL inputs you put in the array must be in FLOAT type.
Change this:
int Parray[n_steps+1];
int Tarray[n_steps+1];
to
float Parray[n_steps+1];
float Tarray[n_steps+1];
and
P_init = 30;
t_init = 0;
t_end = 30;
All of them should be 30.0, 0.0, 30.0
Don't forget this too:
Parray[i]=0;
Tarray[i]=0;
Change it to 0.0
In short, C is bad at differentiate between types, so if you declare a float array, all inputs must be x.0, not only x where x is an integer.

OpenMP paralleling GSL Ordinary Differential Equations calculation

I'm trying to parallelize my code, but i got errors. I need to calc a Cauchy problem (it's already done) but than i need to parallelize it using OpenMP lib.
I've tried to write some code with OpenMP, but it's not working.
I've created a struct to collect result.
struct Dots {
double par;
double x;
double y;
};
This is my target function with parameter.
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = x + 2 * y[0] / (1 + mu * mu);
return GSL_SUCCESS;
}
This is the main function. I currently didn't find a way how to create a array of arrays of struct, but this is not the main problem.
void calc_cauchy_problem(struct Dots ArrayOfDots[], double x_start, double x_end, double y_start,
int count) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int mu = 5;
int param = 0;
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,
gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
int status = 0;
#pragma omp parallel for shared(ArrayOfDots) private(sys, param, d, status)
for (int param = 1; param < mu; param++) {
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,
gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++)
{
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
// ArrayOfDots[i].par = mu;
// ArrayOfDots[i].x = xi;
// ArrayOfDots[i].y = y[0];
}
gsl_odeiv2_driver_free (d);
}
}
The main
int main() {
double x_start = 0;
double x_end = 10;
double y_start = 0;
int count = 10;
struct Dots ArrayOfDots[count];
calc_cauchy_problem(ArrayOfDots, x_start, x_end, y_start, count);
return 0;
}
It's compiled successfully with this gcc main.c -o main -fopenmp -lgsl -std=gnu11 but when i launch it i got error
gsl: driver.c:354: ERROR: integration limits and/or step direction not consistent
Default GSL error handler invoked.
I think that the main problem with this #pragma omp parallel for shared(ArrayOfDots) private(sys, param, d, status) but i have no idea how to rewrite this in the other way.
Thanks for your responses.
UPD:
With Kaveh Vahedipour help my code partially start to work. It means that half of my for cycle start to work.
UPD UPD:
After another investigations i had the following code:
It's compile and run, but i got Process finished with exit code 4 and printf("Elapsed time = %f\n", omp_get_wtime() - start_time); don't print anything.
struct Dots {
double par;
double x;
double y;
};
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = (x + 2 * y[0]) / (1 + mu * mu);
return GSL_SUCCESS;
}
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int param = param1;
int j = 0;
int status = 0;
char filename[10];
#pragma omp parallel for private(param, status, x, y)
for (param = param1; param <= param2; param++) {
struct Dots ArrayOfDots[count];
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++) {
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
}
gsl_odeiv2_driver_free (d);
}
}
int main() {
double start_time = omp_get_wtime();
double x_start = 0;
double x_end = 10;
double y_start = 0;
const int count = 500;
int param1 = 1;
int param2 = 10;
calc_cauchy_problem(x_start, x_end, y_start, count, param1, param2);
printf("Elapsed time = %f\n", omp_get_wtime() - start_time);
return 0;
}
Add x to private loop vars: private(sys, param, d, status, x). Please get back to me, if you still experience issues.
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int param = param1;
int j = 0;
int status = 0;
char filename[10];
#pragma omp parallel for private(param, status, x, y)
for (param = param1; param <= param2; param++) {
struct Dots ArrayOfDots[count];
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++) {
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
}
//write_data_to_file(param, count, ArrayOfDots);
for (int i = 0; i < count; ++i) {
printf ("%d: %f, %f, %f\n", omp_get_thread_num(),
ArrayOfDots[i].par, ArrayOfDots[i].x, ArrayOfDots[i].y);
}
gsl_odeiv2_driver_free (d);
}
}
Seems like this version works fine. I think problem was with this struct Dots ArrayOfDots[count]; and when i try to push values to this struct.
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
Here is the full code.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
// GSL lib includes
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv2.h>
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = (x + 2 * y[0]) / (1 + mu * mu);
return GSL_SUCCESS;
}
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
#pragma omp parallel for
for(int param = param1; param < param2; param++) {
gsl_odeiv2_system sys = {ode_func, NULL, 1, &param};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rk8pd,
1e-6, 1e-6, 0.0);
int i;
double x = x_start, x1 = x_end;
double y[1] = { y_start };
for (i = 1; i <= count; i++)
{
double xi = i * x1 / count;
int status = gsl_odeiv2_driver_apply (d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
// printf ("%d %d %.5e %.5e\n", omp_get_thread_num(), param, x, y[0]);
}
gsl_odeiv2_driver_free (d);
}
}
int main() {
double start_time = omp_get_wtime();
double x_start = 0;
double x_end = 10;
double y_start = 0;
const int count = 100000;
int param1 = 1;
int param2 = 20;
calc_cauchy_problem(x_start, x_end, y_start, count, param1, param2);
printf("Elapsed time = %f\n", omp_get_wtime() - start_time);
return 0;
}
Really thanks to Kaveh Vahedipour.

Monte Carlo integration returning incorrect values, problem overwriting memory

I'm having trouble calculating integrals for the centre of mass of a torus, which should return (2.4076, 0.16210, 0.0).
The program works for an estimation of pi/4 however I think there is an issue when I try to overwrite existing points using the setRandomDomain() function.
Here is my code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define DIM 1000000
double random_double() {
static const int a = 16807;
static const int c = 0;
static const long long m = 2147483647;
static long long seed = 1;
seed = (a * seed + c) % m;
return ((double) seed) / m;
}
typedef struct Domain_t {
double *x;
double *y;
double *z;
} Domain;
void constructDomain(Domain (**p_domain)) {
*p_domain = malloc(sizeof(Domain));
if(p_domain == NULL) {
printf("ERROR: Memory allocation failed\n");
}
(*p_domain)->x = malloc(DIM * sizeof(double));
if ((*p_domain)->x == NULL) {
printf("ERROR: Memory allocation failed\n");
}
(*p_domain)->y = malloc(DIM * sizeof(double));
if ((*p_domain)->y == NULL) {
printf("ERROR: Memory allocation failed\n");
}
(*p_domain)->z = malloc(DIM * sizeof(double));
if((*p_domain)->z == NULL) {
printf("ERROR: Memory allocation failed\n");
}
}
void delDomain (Domain (**p_domain)) {
if (p_domain != NULL) {
free ((*p_domain)->z);
free ((*p_domain)->y);
free ((*p_domain)->x);
free (*p_domain);
}
}
double radiusFunc(double point_x, double point_y) {
return sqrt(pow(point_x,2)+pow(point_y,2));
}
double G(double point_x, double point_y, double point_z, int R) {
return pow(point_z,2)+pow(radiusFunc(point_x,point_y)-(double)R,2);
}
typedef struct Volume_t {
int R;
int r;
int lower_x;
int upper_x;
int lower_y;
int upper_y;
int lower_z;
int upper_z;
int V;
} Volume;
void setVolume(Volume (*p_volume), int R, int r, int x1, int x2, int y1, int y2, int z1, int z2) {
p_volume->R = R;
p_volume->r = r;
p_volume->lower_x = x1;
p_volume->upper_x = x2;
p_volume->lower_y = y1;
p_volume->upper_y = y2;
p_volume->lower_z = z1;
p_volume->upper_z = z2;
if(z1 == 0 && z2 == 0)
p_volume->V = (x2-x1)*(y2-y1);
else if(y1 == 0 && y2 == 0)
p_volume->V = (x2-x1)*(z2-z1);
else if(x1 == 0 && x2 == 0)
p_volume->V = (y2-y1)*(z2-z1);
else
p_volume->V = (x2-x1)*(y2-y1)*(z2-z1);
}
void setInitialDomain(Domain (**p_domain)) {
int i;
for(i=0;i<DIM;i++) {
(*p_domain)->x[i] = random_double();
(*p_domain)->y[i] = random_double();
(*p_domain)->z[i] = random_double();
}
}
void setRandomDomain(Domain (*p_domain), Domain (**p_new_domain), Volume (*p_volume)) {
int i;
for(i=0;i<DIM;i++) {
(*p_new_domain)->x[i] = p_domain->x[i]*(double)(p_volume->upper_x - p_volume->lower_x) + (double)p_volume->lower_x;
(*p_new_domain)->y[i] = p_domain->y[i]*(double)(p_volume->upper_y - p_volume->lower_y) + (double)p_volume->lower_y;
(*p_new_domain)->z[i] = p_domain->z[i]*(double)(p_volume->upper_z - p_volume->lower_z) + (double)p_volume->lower_z;
}
}
double setIntegrand(Domain (*p_domain), char c) {
double *p_x = p_domain->x;
double *p_y = p_domain->y;
double *p_z = p_domain->z;
if(c=='x')
return *p_x;
else if(c=='y')
return *p_y;
else if(c=='z')
return *p_z;
else
return 1.;
}
double calculateIntegral(Domain (*p_domain), Volume (*p_volume), char c) {
int i;
double F = 0.;
for(i=0;i<DIM;i++) {
if(G(p_domain->x[i], p_domain->y[i], p_domain->z[i], p_volume->R)<=(double)p_volume->r) {
F += setIntegrand(p_domain, c);
}
}
return F*(double)p_volume->V/(double)DIM;
}
int main() {
Domain *p_initial_domain;
Domain *p_random_domain;
constructDomain(&p_initial_domain);
printf("Point 1: successful\n");
constructDomain(&p_random_domain);
printf("Point 2: successful\n");
setInitialDomain(&p_initial_domain);
Volume circle, *p_circle;
p_circle = &circle;
setVolume(p_circle,0,1,0,1,0,1,0,0);
setRandomDomain(p_initial_domain, &p_random_domain, p_circle);
printf("PI/4 is approximately %f\n", calculateIntegral(p_random_domain, p_circle, 'p'));
Volume torus, *p_torus;
p_torus = &torus;
setVolume(p_torus,3,1,1,4,-3,4,-1,1);
setRandomDomain(p_initial_domain, &p_random_domain, p_torus);
double M = calculateIntegral(p_random_domain, p_torus, 'p');
double X = calculateIntegral(p_random_domain, p_torus, 'x');
double Y = calculateIntegral(p_random_domain, p_torus, 'y');
double Z = calculateIntegral(p_random_domain, p_torus, 'z');
printf("rho integral is approximately %f\n", M);
printf("x integral is approximately %f\n", X);
printf("y integral is approximately %f\n", Y);
printf("z integral is approximately %f\n", Z);
printf("Centre of mass is approximately (%f, %f, %f)\n", X/M, Y/M, Z/M);
delDomain(&p_initial_domain);
delDomain(&p_random_domain);
// return pointers??
// array of structs??
return 0;
}
Currently outputs:
PI/4 is approximately 0.785436
rho integral is approximately 22.101282
x integral is approximately 22.101801
y integral is approximately -45.953770
z integral is approximately 11.298411
Centre of mass is approximately (1.000023, -2.079235, 0.511211)
Any ideas how to solve this?
Also, please can someone explain how I would use functions returning pointers and why it may be better to create an array of structs instead of a struct of arrays?
Your problem is that you call setIntegrand in a loop over all points, but you always take the first point:
double *p_x = p_domain->x;
// ...
return *p_x;
This returns the first double in your array. Remember that *x is equivalent to x[0]. Pass the index to the function:
double setIntegrand(Domain (*p_domain), char c, int i)
{
if (c == 'x') return p_domain->x[i];
if (c == 'y') return p_domain->y[i];
if (c == 'z') return p_domain->z[i];
return 1.;
}
and then call it with that index.
for (i = 0; i < DIM; i++) {
if (G(...) <= p_volume->r) {
F += setIntegrand(p_domain, c, i);
}
}
As to your additional questions: Using an array of structs keeps the things that go together (here, the three coordinates of the points) nearby. You can also easily just pass a point to a function with a single argument.
If you have a constructor, that is a function that creates a new thing by allocating on the heap and initialising the new memory, returning a pointer is a useful idiom. (I find it more idiomatic than passing a point to a pointer, but whoever designed to fopen_s function didn't think so.)
Let's put both changes together:
typedef struct Point Point;
typedef struct Domain Domain;
struct Point {
double x;
double y;
double z;
};
struct Domain {
size_t length;
Point *point;
};
Domain *constructDomain(size_t length)
{
Domain *dom = malloc(sizeof(*dom));
if (dom) {
dom->length = length;
dom->point = calloc(length, sizeof(*dom->point));
// check success
}
return dom;
}
First note, when possible it generally best to reduce the number of heap allocations and leave variables on the stack, less room for error. I'd say if you want 1M x 3 x sizeof(double) bytes, arround 24M, it is best to dynamically allocate it on the heap. We can leave the structure that holds these on the stack.
Another thing is when you create a variable, you don't need to create another variable to point to it, just use the original variable.
Last note is commenting, I personally comment every line of code but that may be to much here. I find it helpful to write out what exactly you are trying to do with each line of code to help find bugs.
You don't need to return pointers anywhere here i don't think, perhaps when you were passing pointer to a pointer it would have been better to just return a pointer. An array of structures is another way of doing it, it means only one malloc and one free but alignment could cause extra memory to be used (padding) which could be considerable when using 1M points, there likely won't be any padding here tho because you are using double floating points. I think your arrays are fine.
I made some changes with the way you are using pointers, this likely won't solve your problem but it at least cleans things up a bit.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define DIM 1000000
typedef struct Domain_t {
double *x;
double *y;
double *z;
} Domain;
typedef struct Volume_t {
int R;
int r;
int lower_x;
int upper_x;
int lower_y;
int upper_y;
int lower_z;
int upper_z;
int V;
} Volume;
double random_double() {
static const int a = 16807;
static const int c = 0;
static const long long m = 2147483647;
static long long seed = 1;
seed = (a * seed + c) % m;
return ((double) seed) / m;
}
void constructDomain(Domain *p_domain) {
p_domain->x = malloc(DIM * sizeof(double));
if (p_domain->x == NULL) {
printf("ERROR: Memory allocation failed\n");
}
p_domain->y = malloc(DIM * sizeof(double));
if (p_domain->y == NULL) {
printf("ERROR: Memory allocation failed\n");
}
p_domain->z = malloc(DIM * sizeof(double));
if(p_domain->z == NULL) {
printf("ERROR: Memory allocation failed\n");
}
}
void delDomain (Domain *p_domain) {
if (p_domain != NULL) {
free (p_domain->z);
free (p_domain->y);
free (p_domain->x);
}
}
double radiusFunc(double point_x, double point_y) {
return sqrt(pow(point_x,2)+pow(point_y,2));
}
double G(double point_x, double point_y, double point_z, int R) {
return pow(point_z,2)+pow(radiusFunc(point_x,point_y)-(double)R,2);
}
void setVolume(Volume *p_volume, int R, int r, int x1, int x2, int y1, int y2, int z1, int z2) {
p_volume->R = R;
p_volume->r = r;
p_volume->lower_x = x1;
p_volume->upper_x = x2;
p_volume->lower_y = y1;
p_volume->upper_y = y2;
p_volume->lower_z = z1;
p_volume->upper_z = z2;
if(z1 == 0 && z2 == 0)
p_volume->V = (x2-x1)*(y2-y1);
else if(y1 == 0 && y2 == 0)
p_volume->V = (x2-x1)*(z2-z1);
else if(x1 == 0 && x2 == 0)
p_volume->V = (y2-y1)*(z2-z1);
else
p_volume->V = (x2-x1)*(y2-y1)*(z2-z1);
}
void setInitialDomain(Domain *p_domain) {
int i;
for(i=0;i<DIM;i++) {
p_domain->x[i] = random_double();
p_domain->y[i] = random_double();
p_domain->z[i] = random_double();
}
}
void setRandomDomain(Domain *p_domain, Domain *p_new_domain, Volume *p_volume) {
int i;
for(i=0;i<DIM;i++) {
p_new_domain->x[i] = p_domain->x[i] * (double) (p_volume->upper_x - p_volume->lower_x) + (double) p_volume->lower_x;
p_new_domain->y[i] = p_domain->y[i] * (double) (p_volume->upper_y - p_volume->lower_y) + (double) p_volume->lower_y;
p_new_domain->z[i] = p_domain->z[i] * (double) (p_volume->upper_z - p_volume->lower_z) + (double) p_volume->lower_z;
}
}
double setIntegrand(Domain (*p_domain), char c) {
double *p_x = p_domain->x;
double *p_y = p_domain->y;
double *p_z = p_domain->z;
if(c=='x')
return *p_x;
else if(c=='y')
return *p_y;
else if(c=='z')
return *p_z;
else
return 1.0;
}
double calculateIntegral(Domain *p_domain, Volume *p_volume, char c) {
int i;
double F = 0.0;
for(i=0;i<DIM;i++) {
if(G(p_domain->x[i], p_domain->y[i], p_domain->z[i], p_volume->R)<=(double)p_volume->r) {
F += setIntegrand(p_domain, c);
}
}
return F * (double) p_volume->V / (double)DIM;
}
int main() {
Domain initial_domain;
Domain random_domain;
Volume circle;
Volume torus;
/* memory allocation */
constructDomain(&initial_domain);
constructDomain(&random_domain);
/* initialization */
setInitialDomain(&initial_domain);
/* volume */
setVolume(&circle,0,1,0,1,0,1,0,0);
setRandomDomain(&initial_domain, &random_domain, &circle);
/* integral */
printf("PI/4 is approximately %f\n", calculateIntegral(&random_domain, &circle, 'p'));
setVolume(&torus,3,1,1,4,-3,4,-1,1);
setRandomDomain(&initial_domain, &random_domain, &torus);
double M = calculateIntegral(&random_domain, &torus, 'p');
double X = calculateIntegral(&random_domain, &torus, 'x');
double Y = calculateIntegral(&random_domain, &torus, 'y');
double Z = calculateIntegral(&random_domain, &torus, 'z');
printf("rho integral is approximately %f\n", M);
printf("x integral is approximately %f\n", X);
printf("y integral is approximately %f\n", Y);
printf("z integral is approximately %f\n", Z);
printf("Centre of mass is approximately (%f, %f, %f)\n", X/M, Y/M, Z/M);
delDomain(&initial_domain);
delDomain(&random_domain);
return 0;
}

Calculating cos(x) through Maclaurin series approximation using a factorial function and a cosine one

I have an assignment to code a program to calculate cos(x) through the Maclaurin approximation. However I must use a function for the cos(x) and another one to calculate the exponentials that go on the denominators inside the cos(x) function. I think most of this is right, but I'm probably missing on something and I can't figure out what.
#include<stdio.h>
#include <stdlib.h>
#include <math.h>
int fat(int);
float cosx(float);
int main()
{
float x1;
/* Original code: **x1 = x1 * 3.14159 / 180;** `transforms the value to radians` */
x1 = x1 * 3.14159 / 180; /* transforms the value to radians */
printf("Insert number:\n");
scanf("%f", &x1);
printf("Cosine of %f = %f", x1, cosx(x1));
return 0;
}
int fat(int y)
{
int n, fat = 1;
for(n = 1; n <= y; n++)
{
fat = fat * n;
}
return fat;
}
float cosx(float x)
{
int i=1, a = 2, b, c = 1, e;
float cos;
while(i < 20)
{
b = c * (pow(x,a)) / e;
cos = 1 - b;
a += 2;
e = fat(a);
c *= -1;
i++;
}
return cos;
}
If I input 0 it returns -2147483648.000000, which is clearly wrong.
First error is uninitialized variable x1, and right after that you have use:
int x1; // <<< uninitiated variable;
**x1 = x1 * 3.14159 / 180;** `transforms the value to radians
this will produce random value, you should put
int x = 0; // or some other value of your choice
In my opinion you should move x1 = x1 * 3.14159/100; after scanf("%d", x1).
Than again uninitiated value e before use.
int i=1, a = 2, b, c = 1, e;
...
b = c * (pow(x,a)) / e;
...
than you have in the line b = c * pow(x,a) where you go out of range of int variable potentially. If e = 1, x = 2 and a > 31 you are out of range for b. Another problem is pow(x,a) is rising much faster than `e. thus you get bigger and bigger values thus you are getting another overflow. And here is the code that works:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
long double fact(int);
long double cosx(double);
long double my_pow (double b, int e);
int main()
{
double x1 = 45.00;
printf("Insert number:\n");
scanf("%lf", &x1);
x1 = x1 * 3.14159 / 180; // ** `transforms the value to radians`
printf("Cosine of %f = %.10LF", x1, cosx(x1));
return 0;
}
long double fact(int y)
{
int n;
double fact = 1;
for(n = 1; n <= y; n++)
{
fact *= n;
}
return fact;
}
long double cosx(double x)
{
int a = 2, c = -1;
long i = 0, lim = 500;
long double cos = 1;
long double b = 0, e = 0;
while(i < lim) {
e = fact(a);
b = c * my_pow(x,a);
cos += b/e;
// printf ("%le %le %le\n", e, b, cos);
a += 2;
c *= -1;
i++;
}
return cos;
}
long double my_pow (double b, int e) {
long double pow = 1;
for (;e > 0; --e, pow *= b)
;
return pow;
}

Resources