Первое замечание: когда это возможно, обычно лучше уменьшить количество выделений кучи и оставить переменные в стеке, меньше места для ошибок.Я бы сказал, если вы хотите 1M x 3 x sizeof(double)
байт, около 24M, лучше всего динамически распределить его в куче.Мы можем оставить структуру, которая хранит их в стеке.
Другое дело, когда вы создаете переменную, вам не нужно создавать другую переменную, чтобы указывать на нее, просто используйте исходную переменную.
Последнее примечание комментирует, я лично комментирую каждую строку кода, но это может быть много здесь.Я считаю полезным написать, что именно вы пытаетесь сделать с каждой строкой кода, чтобы помочь найти ошибки.
Вам не нужно возвращать указатели где-либо здесь, я не думаю, возможно, когда вы былипередавая указатель на указатель, было бы лучше просто вернуть указатель.Массив структур - это еще один способ сделать это, это означает, что только один malloc и один свободный, но выравнивание может привести к использованию дополнительной памяти (заполнение), что может быть значительным при использовании точек 1M, вероятно, здесь не будет никакого дополнения, хотяпотому что вы используете двойные с плавающей запятой.Я думаю, с вашими массивами все в порядке.
Я внес некоторые изменения в то, как вы используете указатели, это, вероятно, не решит вашу проблему, но, по крайней мере, немного прояснит ситуацию.
#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;
}