So I had one large function that worked. Then I decided to modify it and now I am just printing out a black square. I am attaching my code to see if any one would understand what is happening. These three function where once large function:
Function 1
int
readpgm (pgm_type * header, char input[80], char output[80])
{
FILE *instream;
int size, read;
instream = fopen (input, "rb");
fileChecker (instream);
fscanf (instream, "%2s%d%d%d", header->filetype, &header->width,
&header->height, &header->maxgray);
if (!header->filetype[0] == 'P' || !header->filetype[1] == '5') {
fatal ("Incorrect Type");
}
size = header->width * header->height;
header->p = malloc (size * sizeof (char));
read = fread (header->p, 1, size, instream);
if (read != size) {
fatal ("Incorrect Size");
}
return size;
}
void
crop (pgm_type * header, char output[80])
{
printf ("Height: %i, Width: %i, Total pixels: %i \n", header->height,
header->width, header->height * header->width);
int temp, y1, y2, x1, x2, wide, high;
printf ("Please Enter x1 y1 x2 y2 \n");
scanf ("%i %i %i %i", &x1, &y1, &x2, &y2);
if (y1 > y2) {
temp = y1;
y1 = y2;
y2 = temp;
}
if (x1 > x2) {
temp = x1;
x1 = x2;
x2 = temp;
}
wide = x2 - x1 + 1;
high = y2 - y1 + 1;
printFile (wide, high, x1, x2, y1, y1, header, output);
}
void
printFile (int wide, int high, int x1, int x2, int y1, int y2,
pgm_type * header, char output[80])
{
FILE *outstream;
outstream = fopen (output, "wb");
fileChecker (outstream);
fprintf (outstream, "%2s\n%i %i\n%i\n", header->filetype, wide, high,
header->maxgray);
pixel image[header->height][header->width];
pixel *pix = malloc ((wide * high) * sizeof (char));
int a = 0;
for (int b = 0; b < header->height; ++b) {
for (int c = 0; c < header->width; ++c) {
image[b][c] = header->p[a];
++a;
}
}
int k = 0;
for (int i = y1; i <= y2; ++i) {
for (int j = x1; j <= x2; ++j) {
pix[k] = image[i][j];
++k;
}
}
fwrite (pix, 1, (wide * high) * sizeof (pixel), outstream);
free (pix);
fclose (outstream);
}
The first two function are call in main.
This works for me.
//gcc c2.c -std=c99 -g -Wall -Wextra
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
typedef struct pgm_type pgm_type;
struct pgm_type{
char filetype[2];
int width,height,maxgray;
unsigned char*p;
};
int
readpgm (pgm_type * header, char*fn)
{
FILE *instream;
int size, read;
instream = fopen (fn,"rb");
assert(instream);
fscanf (instream, "%2s%d%d%d", header->filetype, &header->width,
&header->height, &header->maxgray);
printf("%2s %d %d %d\n",header->filetype,header->width,
header->height,header->maxgray);
if (!header->filetype[0] == 'P' || !header->filetype[1] == '5') {
printf ("Incorrect Type");
}
size = header->width * header->height;
header->p = malloc (size * sizeof (char));
read = fread (header->p, 1, size, instream);
if (read != size) {
printf ("Incorrect Size");
}
return size;
}
void
printFile (int x1, int x2, int y1, int y2,pgm_type * header, char*fn)
{
FILE *outstream;
int wide=x2-x1+1,high=y2-y1+1;
printf("cropping to %dx%d\n",wide,high);
outstream = fopen (fn, "wb");
assert (outstream);
fprintf (outstream, "%2s\n%i %i\n%i\n", header->filetype, wide, high,
header->maxgray);
unsigned char image[header->height][header->width];
unsigned char *pix = malloc ((wide * high) * sizeof (char));
int a = 0;
for (int b = 0; b < header->height; ++b) {
for (int c = 0; c < header->width; ++c) {
image[b][c] = header->p[a];
++a;
}
}
int k = 0;
for (int j = y1; j <= y2; ++j) {
for (int i = x1; i <= x2; ++i) {
pix[k] = image[j][i];
++k;
}
}
fwrite (pix, wide,high, outstream);
free (pix);
fclose (outstream);
}
int
main()
{
pgm_type h;
readpgm(&h,"lena.pgm");
printFile(64,129,32,230,&h,"o2.pgm");
return 0;
}
Related
I'm trying to implement Hough algorithm using C programming language and 2D raw image.
I have written the code in order to get separate output image for edge detection and Hough transform. When I do edge detection only I'm getting the proper edge detected output image. But here I'm getting the output raw image of size 0KB.I'm not getting where I made mistake.
Can anybody please help me to rectify this problem and give idea for further development such as draw line based on Hough space for the below code.
Thank you in advance.
#include <stdio.h>
#include <math.h>
#define PI 3.14159265
void
hough_transform(unsigned char out[256][256], unsigned char h_out[][256],
int w, int h)
{
int i, j;
int thetaDeg;
float thetaRad;
int rho;
int distMax;
int thetamax;
distMax = sqrt((h * h) + (w * w));
thetamax = 360;
int Acc[180][180];
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
if (out[i][j] > 0) {
for (thetaDeg = 0; thetaDeg < thetamax; ++thetaDeg) {
thetaRad = thetaDeg * (PI / 180);
rho = i * cos(thetaRad) + j * sin(thetaRad);
// find rho value that is closest to this
if (distMax < rho) {
int min = abs(rho - distMax);
}
if (distMax <= 1) {
// Increment a value in an accumulator array
Acc[rho][thetaDeg] += 1;
}
}
}
}
}
for (rho = 0; rho < distMax; rho++) {
for (thetaDeg = 0; thetaDeg < thetamax; thetaDeg++) {
h_out[rho][thetaDeg] = Acc[rho][thetaDeg];
}
}
}
void
edge_detect(unsigned char input[256][256], unsigned char out[][256],
int width, int height)
{
int in[3][3] = { {1, 2, 1}, {0, 0, 0}, {-1, -2, -1} };
int pixel;
int i;
int j;
int x;
int y;
for (y = 1; y < height - 1; y++) {
for (x = 1; x < width - 1; x++) {
pixel = 0;
for (j = -1; j <= 1; j++) {
for (i = -1; i <= 1; i++) {
pixel += in[j + 1][i + 1] * input[y + j][x + i];
}
}
out[y][x] = (unsigned char) abs(pixel);
}
}
}
int
main()
{
FILE *fp;
FILE *fp1;
FILE *fp2;
unsigned char input[256][256];
unsigned char out[256][256];
unsigned char h_out[256][256];
int width = 256;
int height = 256;
fp = fopen("Image.raw", "rb");
fp1 = fopen("output.raw", "wb");
fp2 = fopen("h_output.raw", "wb");
fread(input, 256 * 256, 1, fp);
edge_detect(input, out, width, height);
hough_transform(out, h_out, width, height);
fwrite(out, 256 * 256, 1, fp1);
fwrite(h_out, 256 * 256, 1, fp2);
fclose(fp);
fclose(fp1);
fclose(fp2);
return (0);
}
I am using Dev C++ compiler to run my C code below. I have used _UADD assembly function to make it more optimized. But I am getting an undefined reference error for _UADD. I have only minimal background in assembly language. Can I use this assembly function _UADD to optimize my C code and compile in Dev C++? If so how?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <x86intrin.h>
#include <stdint.h>
#ifndef N1_8_H
#define N1_8_H
void refined_karatsuba_mul(int16_t* h, const int16_t* f, const int16_t* g, int n);
#endif
static void schoolbook_mul(int16_t* h, const int16_t* f, const int16_t* g, int n)
{
int16_t result;
int i,j;
for (i = 0; i < n; ++i) {
result = 0;
for (j = 0; j <= i; ++j) result = result+f[j]*g[i-j];
h[i] = result;
}
for (i = n; i < n+n-1; ++i) {
result = 0;
for (j = i-n+1; j < n; ++j) result = result+f[j]*g[i-j];
h[i] = result;
}
}
void refined_karatsuba_mul(int16_t* h, const int16_t* f, const int16_t* g, int n) {
const int16_t* f0 = f;
int16_t f01[n/2];
const int16_t* f1 = f + n/2;
const int16_t* g0 = g;
int16_t g01[n/2];
const int16_t* g1 = g + n/2;
uint32_t result;
for (int i = 0; i < n/2; i+=2) {
*(int32_t*)(&f01[i]) = __UADD16(*(int32_t*)(&f0[i]), *(int32_t*)(&f1[i])); // f01[i]= f0[i] + f1[i] and f01[i+1]= f0[i+1] + f1[i+1]
*(int32_t*)(&g01[i]) = __UADD16(*(int32_t*)(&g0[i]), *(int32_t*)(&g1[i])); // g01[i]= g0[i] + g1[i] and g01[i+1]= g0[i+1] + g1[i+1]
}
int16_t p1[n-1], p2[n-1], p3[n-1];
schoolbook_mul(p1, f0, g0, n/2);
schoolbook_mul(p2, f01, g01, n/2);
schoolbook_mul(p3, f1, g1, n/2);
for(int i = 0; i < n-1; i++) {
h[i] += p1[i];
h[i+n/2] += p2[i] - p1[i] - p3[i];
h[i+n] += p3[i];
}
}
int main(){
int16_t *f = malloc(8*sizeof(int16_t));
int16_t *g = malloc(8*sizeof(int16_t));
int16_t *h= calloc((2*8-1), sizeof(int16_t));
int i;
////////////////////////reading f and g
FILE *myFile;
myFile = fopen("inp8test", "r");
if (myFile == NULL){
printf("Error Reading File\n");
exit (0);}
for (i = 0; i < 8; i++){
fscanf(myFile, "%d", &f[i]);
f[i] = 0;
}
for (i = 0; i < 8; i++){
fscanf(myFile, "%d", &g[i] );
g[i] = 0;
}
fclose(myFile);
unsigned long long LastCycleCount = _rdtsc();
clock_t start = clock ();
for (i=0;i<999;i++){
refined_karatsuba_mul(h, f, g, 8);
memset(h, 0, sizeof(int16_t)*(2*8-1));
}
refined_karatsuba_mul(h, f, g, 8);
unsigned long long EndCycleCount = _rdtsc();
unsigned long long CyclesElapsed = EndCycleCount - LastCycleCount;
CyclesElapsed = CyclesElapsed/1000 ;
double Timelapsed=(clock()-start)/(double) CLOCKS_PER_SEC;
Timelapsed=Timelapsed/1000;
/////////////////////////////////////////////write on c_n1_8 file
FILE *outFile;
outFile = fopen("c_n1_8", "w");
if (outFile == NULL)
{
printf("Cannot Open File\n");
exit (0);
}
for (i = 0; i < 2*8-1; i++)
fprintf(outFile, "%d ", ((h[i])%3+3)%3 );
fclose(outFile);
/////////////////////////////////////////////////////////////printing on console
for( i=0; i<2*8-1; i++)
printf("%d ", ((h[i])%3+3)%3);
printf("\n\n\n");
printf("Cycles: %llu\n", CyclesElapsed);
printf("Multiplication Time:");
printf( "%f",Timelapsed);
printf("sec");
printf("\n \n ");
free(f);
free(g);
free(h);
return 0;
}
My programm reads values from a file and stores them in xArray and yArray. I tried to implement linear regression algorithm, it works but after certain point stops calculating correctly and error is getting bigger and bigger. Where is my error?
The desired f(x) : = 2x + 0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define SIZE 20 //size of the sample input array
#define iterations_number 100
#define PI 3.14159
double start_value = 5.5;
double xArray[SIZE] = { 0 };
double yArray[SIZE] = { 0 };
int array_size = sizeof(xArray) / sizeof(xArray[0]);
FILE* file;
FILE* file_xArray;
FILE* file_yArray;
FILE* sample;
void print_result(double b0, double b1, double error);
void calculate(); //calculate the best linear function
double calculateAngle(double x2, double y2, double x1, double y1);
void add_next_item_to_buffer_and_remove_last_item(double item, double* buffer);
void generate_first_sample_data_and_fill_xArray();
void generate_first_sample_data_and_fill_yArray();
void generate_first_sample_data();
void print_xArray();
void print_yArray();
void read_from_file_and_fill_xArray_and_yArray();
void reverseArray(int arr[], int start, int end);
void main(){
generate_first_sample_data();
read_from_file_and_fill_xArray_and_yArray();
reverseArray(xArray, 0, 2*SIZE);
reverseArray(yArray, 0, 2*SIZE);
calculate();
// print_xArray();
// print_yArray();
}
void add_next_item_to_buffer_and_remove_last_item(double item, double *buffer) {
for (int i = SIZE - 1; i > 0; i--) {
buffer[i] = buffer[i - 1];
}
buffer[0] = item;
}
void print_result(double b0, double b1, double error) {
printf("f(x) = %5f x + %5f\n", b1, b0);
printf("Error: %5f ", error);
}
void print_xArray() {
for (int i = 0; i < array_size; i++) {
printf("%f\n", xArray[i]);
}
}
void print_yArray() {
for (int i = 0; i <array_size; i++) {
printf("%f\n", yArray[i]);
}
}
void calculate() {
double y = 1;
double err = 5.0;
double b0 = 0.0;
double b1 = 0.0;
double alpha = 0.01; //error rate
double degree = 0;
double prediction_number = 0.0;
errno_t returnValue = fopen_s(&file, "data.txt", "w" );
fprintf(file, "SAMPLE_NO, ITERATION_NO, REF_VAL, MEASUREMENT, ERROR\n");
for (int i = 0; i < iterations_number; i++) {
int L = i % SIZE; // L - iteration length - number of samples per iteration
for (int j = 0; j < L; j++) {
y = b0 + b1 * xArray[j]; //y - predicted y value, xArray[i] - x value
}
err = y - yArray[L];
b0 = b0 - alpha * err;
b1 = b1 - alpha * err * xArray[L];
degree = calculateAngle(xArray[L], y, 0.0, 0.0);
print_result(b0, b1, err);
fprintf(file, "%.5f ", xArray[L]);
fprintf(file, "%d. ", i);
fprintf(file, "%.5f ", y);
fprintf(file, "%.5f ", degree);
fprintf(file, "%.5f\n", err);
}
fclose(file);
print_result(b0, b1, err);
}
double calculateAngle(double x2, double y2, double x1, double y1){
double deltaX = x2 - x1;
double deltaY = y2 - y1;
double rad = atan2(deltaY, deltaX); //radians
double degree = rad * (180 / PI);
return degree;
}
void generate_first_sample_data_and_fill_xArray() {
//first data randomly generated
errno_t returnValue = fopen_s(&file_xArray, "xArray.txt", "w");
for (int i = 0; i < array_size; i++) {
xArray[i] = 1.37 + i * 0.3;
fprintf(file_xArray, "%f\n", xArray[i]);
}
fclose(file_xArray);
}
void generate_first_sample_data_and_fill_yArray() {
//first data randomly generated
errno_t returnValue = fopen_s(&file_yArray, "yArray.txt", "w");
for (int i = 0; i < array_size; i++) {
yArray[i] = 1.02 + i * 2.0;
fprintf(file_yArray, "%f\n", yArray[i]);
}
fclose(file_yArray);
}
void generate_first_sample_data() {
errno_t returnValue = fopen_s(&sample, "sample.txt", "w");
for (int i = 0; i < array_size; i++) {
xArray[i] = i;
fprintf(sample, "%f ", xArray[i]);
yArray[i] = i * 2.0;
fprintf(sample, "%f\n", yArray[i]);
}
fclose(sample);
}
void read_from_file_and_fill_xArray_and_yArray() {
errno_t returnValue = fopen_s(&sample, "sample.txt", "r");
char line[SIZE];
const char* standard_white_space = " ";
char* xCoordinate= '\0';
char* yCoordinate= '\0';
while (fgets(line, sizeof line, sample) != NULL) {
// printf("%s\n", buffer);
// Token will point to the part before the
xCoordinate = strtok(line, standard_white_space);
add_next_item_to_buffer_and_remove_last_item(atof(xCoordinate), &xArray);
// Token will point to the part after the
yCoordinate = strtok(NULL, standard_white_space);
add_next_item_to_buffer_and_remove_last_item(atof(yCoordinate), &yArray);
}
fclose(sample);
}
//example of reading from file in format
//x y degree
void read_from_file() {
errno_t returnValue = fopen_s(&sample, "sample.txt", "r");
char line[sizeof(xArray)];
char* search1 = " ";
char* search2= " ";
char* token;
while (fgets(line, sizeof line, sample) != NULL) {
// printf("%s\n", buffer);
// Token will point to the part before the " "
token = strtok(line, search1);
add_next_item_to_buffer_and_remove_last_item(strtod(token, NULL), &xArray);
// Token will point to the part after the " "
token = strtok(search1, search2);
add_next_item_to_buffer_and_remove_last_item(strtod(token, NULL), &yArray);
// Token will point to the part at end of the line
token = strtok(NULL, search2);
//add_next_item_to_buffer_and_remove_last_item(strtod(token, NULL), °reeArray);
}
fclose(sample);
}
void reverseArray(int arr [], int start, int end)
{
if (start >= end)
return;
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
// Recursive Function calling
reverseArray(arr, start + 1, end - 1);
}
Given sample file |xCoordinate yCoordinate|
sample file
Output: output
Sometimes i get also this exception nullptrExceptrion
here
yCoordinate = strtok(NULL, standard_white_space);
add_next_item_to_buffer_and_remove_last_item(atof(yCoordinate), &yArray);
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;
}
I'm developing a program that read from CSV file and calculate score with a method "calculateMLpa". The method receive array of char and array of 10 float, and transform array of float in matrix 3x3. When read the position 3rd number from array, insert in matrix the 4th number and same for 6th number.
I.E.
array value[]={0.000000;123.814934;234.000000;100.000000;166.000000; 203.086639;383.000000;186.000000;338.000000;173.098419 }
array traj[]={"0-0";"0-1";"0-2";"1-0";"1-1";"1-2";"2-0";"2-1";"2-2"}
Xn_val[]={"0","1","2"}
When transform in matrix the result is:
123.814934 234.000000 166.000000
166.000000 203.086639 186.000000
186.000000 338.000000 173.098419
While the expected for [0;2] is 100.000000 and for [1;2]=383.000000, but when print the currently value of traj it's correct.
How can I fix this problem?
The code is all here:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <math.h>
#include <stdbool.h>
#include <ctype.h>
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
int csv_parse ( char *line, int size )
{
char *p;
char *dp;
int inquote;
int na;
int nTo_comma;
char prevc = ',';
char *list[256];
dp = NULL;
// inquote = 0;
na = 0;
prevc = ';';
nTo_comma=0;
for ( p = line; *p != '\n'; p++ )
{
nTo_comma++;
list[nTo_comma] = p;
if(*p == prevc)
{
printf("%s\t", list);
return na;
}
}
printf("\n");
return na;
}
double calculateMLpa(const char *Xn_val[], char *traj[], float value[], double alphaxixj, double tauxi, int sz, int dim) {
double mlx = 0;
double v;
double alphaxi;
char *state;
int i;
int p;
int j;
int k;
// int sz = sizeof(Xn_val) / sizeof(int);
// int dim = sizeof(traj) / sizeof(char);
double trns[sz][sz];
double m[sz];
char *trat="-";
// m[xi] values: the number of transitions leaving the state xi
printf("%d %d \n",sz,dim);
int cont=0;
for (i = 0; i <= sz; i++) {
m[i] = 0.0;
for (j = 0; j <= sz; j++) {
v = 0.0;
int newlength = strlen(Xn_val[i])+strlen(trat)+strlen(Xn_val[j])+1;
state = malloc(sizeof(char)*newlength);
if(state != NULL){
state[0] = '\0';
strcat(state,Xn_val[i]);
strcat(state,trat);
strcat(state,Xn_val[j]);
printf("%s ",state);
}else {
printf(stderr,"malloc failed!\n");
}
// for (k=0; k<=dim;++k){
if (traj[cont] != NULL ){
if (strcmp(traj[cont],state)==0){
v = value[cont+1];
printf("%f \n",v);
}
}
trns[i][j] = v;
printf("%f - \n",trns[i][j]);
if (strcmp(Xn_val[i],Xn_val[j])!=0)
m[i] = m[i] + v;
cont++;
}
}
for (i=0;i<=sz;++i){
for(j=0;j<=sz;++j){
printf("%f ",trns[i][j]);
}
printf("\n");
}
for (p=0;p<=sz;++p){
printf("%f - \n",m[p]);
}
printf("%f %f\n",trns[0][1],trns[0][2]);
alphaxi = alphaxixj * (((double) sz) - 1.0);
alphaxi = alphaxixj;
printf("%d ",sz);
for (i = 0; i <= sz; i++) {
for (j = 0; j <= sz; j++) {
// xi!=xj
if (strcmp(Xn_val[i], Xn_val[j])!=0) {
mlx = mlx + lgamma(alphaxixj + trns[i][j]) - lgamma(alphaxixj);
}
// xi
else {
mlx = mlx + lgamma(alphaxi) - lgamma(alphaxi + m[i]);
mlx = mlx + lgamma(alphaxi + m[i] + 1.0)+ (alphaxi + 1.0) * log(tauxi);
mlx = mlx - lgamma(alphaxi + 1.0)- (alphaxi + m[i] + 1.0) * log(tauxi + trns[i][j]);
}
}
}
return (mlx);
}
#define MAXFLDS 200 /* maximum possible number of fields */
#define MAXFLDSIZE 32 /* longest possible field + 1 = 31 byte field */
void parse(char *record, char *delim, char arr[][MAXFLDSIZE], int *fldcnt) {
char*p = strtok(record, delim);
int fld = 0;
while (p) {
strcpy(arr[fld], p);
fld++;
p = strtok('\0', delim);
}
*fldcnt = fld;
}
void main() {
printf("inizio\n");
FILE *pf;
int N=20;
bool first=true;
const char *a[]={"0","1","2"};
char *traject[]={"0-0","0-1","0-2","1-0","1-1","1-2","2-0","2-1","2-2"};
double bs=0;
char *trat="-";
pf=fopen("//home//user//prova.csv","r");
float array[10][10];
float *t;
char *str= "hello";
char *state;
t = (float *)malloc(N * sizeof(float));
int f=0;
if (pf)
{
size_t i, j, k;
char buffer[BUFSIZ], *ptr;
/*
* Read each line from the file.
*/
for ( i = 0; fgets(buffer, sizeof buffer, pf); ++i )
{
/*
* Parse the comma-separated values from each line into 'array'.
*/
for ( j = 0, ptr = buffer; j < ARRAYSIZE(*array); ++j, ++ptr )
{
array[i][j] = strtof(ptr, &ptr);
}
}
fclose(pf);}
else /* fopen() returned NULL */
{
perror(pf);
}
for(f=0; f<10; ++f){
if(f==0){}
else if(f==1 && array[f][8]==0)
array[f][8]=123.8149353;
t[f]=array[f][8];
//printf("%f \n",t[f]);
}
for (f=0;f<10; ++f){
printf("%f - ",t[f]);
}
//printf("%s, %s, %s \n",a[0],a[1],a[2]);
printf("start\n");
int sz = sizeof(a) / sizeof(char);
int dim = sizeof(traject) / sizeof(char);
printf("%d , %d \n",sz,dim);
bs=calculateMLpa(a,traject,t,1.0,0.1,sz,dim);
printf("done \n");
printf("%f ",bs);
}
EDIT
I try to pass array size
sz=sizeof(a)/sizeof(char)
dim = sizeof(traject) / sizeof(char);
but their value is 24 and 72 respectively, and the execution stops at 0-2 value 100.000000
Arrays passed to functions decay to pointers to the start of the array. So
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
Will not return anything meaningful when checking for its size in that case
To fix, pass the Array size as an additional Argument.
One major problem is that when you pass arrays to functions, they decay to pointers, and the sizeof trick you use to get the array size will not work.
You need to pass the actual array sizes as arguments.