problems with compiling openMP and math library - c

I'm trying to compile a program with openMP:
gcc -c fopenmp -lm prog.c -o prog
prog.c includes . However when I run ./prog, the error is:
bash: ./prog: Permission denied
I tried again without the -c flag:
gcc -o prog -fopenmp -lm prog.c
But this time it doesn't seem to see the functions in math library like cos, sqrt (undefined reference).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <omp.h>
#define REAL float
#define NX (64)
#ifndef M_PI
#define M_PI (3.1415926535897932384626)
#endif
void init(REAL *buff, const int nx, const int ny, const int nz,
const REAL kx, const REAL ky, const REAL kz,
const REAL dx, const REAL dy, const REAL dz,
const REAL kappa, const REAL time) {
REAL ax, ay, az;
int jz, jy, jx;
ax = exp(-kappa*time*(kx*kx));
ay = exp(-kappa*time*(ky*ky));
az = exp(-kappa*time*(kz*kz));
for (jz = 0; jz < nz; jz++) {
for (jy = 0; jy < ny; jy++) {
for (jx = 0; jx < nx; jx++) {
int j = jz*nx*ny + jy*nx + jx;
REAL x = dx*((REAL)(jx + 0.5));
REAL y = dy*((REAL)(jy + 0.5));
REAL z = dz*((REAL)(jz + 0.5));
REAL f0 = (REAL)0.125
*(1.0 - ax*cos(kx*x))
*(1.0 - ay*cos(ky*y))
*(1.0 - az*cos(kz*z));
buff[j] = f0;
}
}
}
}
REAL accuracy(const REAL *b1, REAL *b2, const int len) {
REAL err = 0.0;
int i;
for (i = 0; i < len; i++) {
err += (b1[i] - b2[i]) * (b1[i] - b2[i]);
}
return (REAL)sqrt(err/len);
}
typedef void (*diffusion_loop_t)(REAL *f1, REAL *f2, int nx, int ny, int nz,
REAL ce, REAL cw, REAL cn, REAL cs, REAL ct,
REAL cb, REAL cc, REAL dt,
REAL **f_ret, REAL *time_ret, int *count_ret);
static void
diffusion_baseline(REAL *f1, REAL *f2, int nx, int ny, int nz,
REAL ce, REAL cw, REAL cn, REAL cs, REAL ct,
REAL cb, REAL cc, REAL dt,
REAL **f_ret, REAL *time_ret, int *count_ret) {
REAL time = 0.0;
int count = 0;
do {
int z;
for (z = 0; z < nz; z++) {
int y;
for (y = 0; y < ny; y++) {
int x;
for (x = 0; x < nx; x++) {
int c, w, e, n, s, b, t;
c = x + y * nx + z * nx * ny;
w = (x == 0) ? c : c - 1;
e = (x == nx-1) ? c : c + 1;
n = (y == 0) ? c : c - nx;
s = (y == ny-1) ? c : c + nx;
b = (z == 0) ? c : c - nx * ny;
t = (z == nz-1) ? c : c + nx * ny;
f2[c] = cc * f1[c] + cw * f1[w] + ce * f1[e]
+ cs * f1[s] + cn * f1[n] + cb * f1[b] + ct * f1[t];
}
}
}
REAL *t = f1;
f1 = f2;
f2 = t;
time += dt;
count++;
} while (time + 0.5*dt < 0.1);
*time_ret = time;
*f_ret = f1;
*count_ret = count;
return;
}
static void
diffusion_openmp(REAL *f1, REAL *f2, int nx, int ny, int nz,
REAL ce, REAL cw, REAL cn, REAL cs, REAL ct,
REAL cb, REAL cc, REAL dt,
REAL **f_ret, REAL *time_ret, int *count_ret) {
#pragma omp parallel
{
REAL time = 0.0;
int count = 0;
REAL *f1_t = f1;
REAL *f2_t = f2;
#pragma omp master
printf("%d threads running\n", omp_get_num_threads());
do {
int z;
#pragma omp for
for (z = 0; z < nz; z++) {
int y;
for (y = 0; y < ny; y++) {
int x;
for (x = 0; x < nx; x++) {
int c, w, e, n, s, b, t;
c = x + y * nx + z * nx * ny;
w = (x == 0) ? c : c - 1;
e = (x == nx-1) ? c : c + 1;
n = (y == 0) ? c : c - nx;
s = (y == ny-1) ? c : c + nx;
b = (z == 0) ? c : c - nx * ny;
t = (z == nz-1) ? c : c + nx * ny;
f2_t[c] = cc * f1_t[c] + cw * f1_t[w] + ce * f1_t[e]
+ cs * f1_t[s] + cn * f1_t[n] + cb * f1_t[b] + ct * f1_t[t];
}
}
}
REAL *t = f1_t;
f1_t = f2_t;
f2_t = t;
time += dt;
count++;
} while (time + 0.5*dt < 0.1);
#pragma omp master
{
*f_ret = f1_t;
*time_ret = time;
*count_ret = count;
}
}
return;
}
int main(int argc, char *argv[])
{
struct timeval time_begin, time_end;
int nx = NX;
int ny = NX;
int nz = NX;
REAL *f1 = (REAL *)malloc(sizeof(REAL)*NX*NX*NX);
REAL *f2 = (REAL *)malloc(sizeof(REAL)*NX*NX*NX);
REAL time = 0.0;
int count = 0;
REAL l, dx, dy, dz, kx, ky, kz, kappa, dt;
REAL ce, cw, cn, cs, ct, cb, cc;
l = 1.0;
kappa = 0.1;
dx = dy = dz = l / nx;
kx = ky = kz = 2.0 * M_PI;
dt = 0.1*dx*dx / kappa;
init(f1, nx, ny, nz, kx, ky, kz, dx, dy, dz, kappa, time);
ce = cw = kappa*dt/(dx*dx);
cn = cs = kappa*dt/(dy*dy);
ct = cb = kappa*dt/(dz*dz);
cc = 1.0 - (ce + cw + cn + cs + ct + cb);
diffusion_loop_t diffusion_loop = diffusion_baseline;
if (argc == 2) {
if (strcmp(argv[1], "openmp") == 0) {
diffusion_loop = diffusion_openmp;
}
}
gettimeofday(&time_begin, NULL);
diffusion_loop(f1, f2, nx, ny, nz, ce, cw, cn, cs, ct, cb, cc, dt,
&f1, &time, &count);
gettimeofday(&time_end, NULL);
REAL *answer = (REAL *)malloc(sizeof(REAL) * nx*ny*nz);
init(answer, nx, ny, nz, kx, ky, kz, dx, dy, dz, kappa, time);
REAL err = accuracy(f1, answer, nx*ny*nz);
double elapsed_time = (time_end.tv_sec - time_begin.tv_sec)
+ (time_end.tv_usec - time_begin.tv_usec)*1.0e-6;
REAL mflops = (nx*ny*nz)*13.0*count/elapsed_time * 1.0e-06;
double thput = (nx * ny * nz) * sizeof(REAL) * 2.0 * count
/ elapsed_time / (1 << 30);
fprintf(stderr, "elapsed time : %.3f (s)\n", elapsed_time);
fprintf(stderr, "flops : %.3f (MFlops)\n", mflops);
fprintf(stderr, "throughput : %.3f (GB/s)\n", thput);
fprintf(stderr, "accuracy : %e\n", err);
free(answer);
free(f1);
free(f2);
return 0;
}

In your first case, the -c flag only compiles to an object file, not an actual executable. Since object files don't normally have the executable bit set (because they're not directly executable), you get the Permission denied error.
In your second case, it's because the order in which you specify -l libraries is important. You need to move -lm after your prog.c file, like this:
gcc -o prog -fopenmp prog.c -lm

Related

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.

openMP and Mandelbrot in C

I have to parallelize using openMP the serial version of a program in C to visualize a Mandelbrot set. I tried to do it but I obtain something really strange.
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include "pngwriter.h"
#include "consts.h"
unsigned long get_time()
{
struct timeval tp;
gettimeofday(&tp, NULL);
return tp.tv_sec * 1000000 + tp.tv_usec;
}
int main(int argc, char** argv)
{
png_data* pPng = png_create(IMAGE_WIDTH, IMAGE_HEIGHT);
double x, y, x2, y2, cx, cy;
cy = MIN_Y;
double fDeltaX = (MAX_X - MIN_X) / (double)IMAGE_WIDTH;
double fDeltaY = (MAX_Y - MIN_Y) / (double)IMAGE_HEIGHT;
long nTotalIterationsCount = 0;
unsigned long nTimeStart = get_time();
long i, j, n;
n = 0;
int c;
#pragma omp parallel
{
#pragma omp for private(i, c) reduction(+ : cx, cy)
for (j = 0; j < IMAGE_HEIGHT; j++) {
cx = MIN_X;
for (i = 0; i < IMAGE_WIDTH; i++) {
x = cx;
y = cy;
x2 = x * x;
y2 = y * y;
for (n = 0; (n < MAX_ITERS) && (x2 + y2 < 4); n++) {
y = 2 * x * y + cy;
x = x2 - y2 + cx;
x2 = x * x;
y2 = y * y;
}
int c = ((long)n * 255) / MAX_ITERS;
png_plot(pPng, i, j, c, c, c);
cx += fDeltaX;
nTotalIterationsCount++;
}
cy += fDeltaY;
}
}
unsigned long nTimeEnd = get_time();
png_write(pPng, "mandel.png");
return 0;
}
I obtain this:
https://usi365-my.sharepoint.com/personal/fabbrl_usi_ch/_layouts/15/guestaccess.aspx?guestaccesstoken=d83LRC8EG1Kec%2f%2f6zwCbiHkO7%2bsuGv7JyWR%2flalvPvA%3d&docid=128ed81bef8b244d680d5651ad1afea2f&rev=1
Since this is an assignment, I am not here to ask for code. Just an explanation. Thanks.

parallelize Mandelbrot with OpenMP

I have a function which calculate mandelbrot set I'm trying to parallelize it using openMP.
I put #pragma omp parallel for private before each for
static void calculer (Image * im, int nb_iter, double x_min, double x_max, double y_min, double y_max) {
/* Discretisation de l'ensemble */
double pasx = (x_max - x_min) / im -> nb_col;
double pasy = (y_max - y_min) / im -> nb_lig;
double cy = y_min;
double new_zx;
unsigned int l,c;
// Calcul
#pragma omp parallel for private ( pasx, pasy, im,nb_iter,x_min,x_max,y_min, y_max)
for (l = 0; l < im->nb_lig; l++) {
double cx = x_min;
#pragma omp parallel for private (cx)
for (c = 0; c < im->nb_col; c++) {
double zx = 0.0;
double zy = 0.0;
unsigned int n = 0;
while ( ( zx*zx + zy*zy < 4.0 ) && ( n < nb_iter ) ) {
new_zx = zx*zx - zy*zy + cx;
zy = 2.0*zx*zy + cy;
zx = new_zx;
++n;
}
im->pixels[l*im->nb_col + c] = n%256;
cx += pasx;
}
cy += pasy;
}
}
When compiling using gcc mandelbrot.c -fopenmp -o exe, I get segmentation fault. What could be the possible reason for it?
EDIT: After executing vingrid I get this message
Process terminating with default action of signal 11 (SIGSEGV)
==10689== Access not within mapped region at address 0x0
==10689== at 0x40105F: calculer._omp_fn.0 (in /home/haddad/Documents/TPOpenMP/TP_OpenMP/TP_Mandelbrot/exe3)
==10689== by 0x4E39EE9: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==10689== by 0x5047E99: start_thread (pthread_create.c:308)
==10689== by 0x535038C: clone (clone.S:112)
==10689== If you believe this happened as a result of a stack
==10689== overflow in your program's main thread (unlikely but
==10689== possible), you can try to increase the size of the
==10689== main thread stack using the --main-stacksize= flag.
==10689== The main thread stack size used in this run was 8388608.
I went ahead and cleaned up your code and even made an image from it.
#include <stdlib.h>
#include <stdio.h>
struct Image {
unsigned nb_lig;
unsigned nb_col;
unsigned *pixels;
};
void calculer (struct Image * im, unsigned nb_iter, double x_min, double x_max, double y_min, double y_max) {
double pasx = (x_max - x_min) / im -> nb_col;
double pasy = (y_max - y_min) / im -> nb_lig;
unsigned l,c;
#pragma omp parallel for private (c)
for (l = 0; l < im->nb_lig; l++) {
for (c = 0; c < im->nb_col; c++) {
double zx = 0.0, zy = 0.0, new_zx;
double cx = x_min + c*pasx, cy = y_min + l*pasy;
unsigned n = 0;
for(n=0; (zx*zx + zy*zy < 4.0 ) && ( n < nb_iter ); n++ ) {
new_zx = zx*zx - zy*zy + cx;
zy = 2.0*zx*zy + cy;
zx = new_zx;
}
if(n == nb_iter) n = 0;
im->pixels[l*im->nb_col + c] = n;
}
}
}
void draw_image(struct Image *im) {
const char charset[] = ".,c8M#jawrpogOQEPGJ";
unsigned l,c;
for (l = 0; l < im->nb_lig; l++) {
for (c = 0; c < im->nb_col; c++) {
unsigned n = im->pixels[l*im->nb_col + c];
char p = n > 0 ? charset[n % (sizeof(charset)-1)] : ' ';
putchar(p);
if(c+1 == im->nb_col) puts("");
}
}
puts("");
}
int main(void) {
struct Image im;
im.nb_lig = 40;
im.nb_col = 80;
im.pixels = malloc(sizeof *im.pixels * im.nb_lig*im.nb_col);
unsigned nb_iter = 256;
calculer(&im, nb_iter, -2.5, 1.5, -2.0, 2.0);
draw_image(&im);
return 0;
}
The output is
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccc,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccccccccccccc,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccccccccccccccccccccc,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccccccccccccccccccccccccc,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccccccccccccccccccccccccccccccc,,,
,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccccccccccccccccccccccccccccccccccc,
,,,,,,,,,,,,,,,,,,,,ccccccccccccccc88888888888cccccccccccccccccccccccccccccccccc
,,,,,,,,,,,,,,,,,,,ccccccccc8888888888888888888888888ccccccccccccccccccccccccccc
,,,,,,,,,,,,,,,,,ccccccc8888888888888888MMMMM#.w##MMM8888ccccccccccccccccccccccc
,,,,,,,,,,,,,,,,ccccc8888888888888888MMMMMM##jaoro #MMMM8888cccccccccccccccccccc
,,,,,,,,,,,,,,,ccc8888888888888888MMMMMMM###jwrG#owj##MMMM88888ccccccccccccccccc
,,,,,,,,,,,,,,cc8888888888888888MMMMMMM##jjawQ Jwj####MM888888ccccccccccccccc
,,,,,,,,,,,,,cc88888888888888MMMMMM##jawwwwrpQ OprwjjjJ#MM88888cccccccccccccc
,,,,,,,,,,,,cc8888888888888MMMM####jjagM Pa ,gQEPE#M888888ccccccccccccc
,,,,,,,,,,,,c88888888888MM#######jjjwQg# ,aj#M888888cccccccccccc
,,,,,,,,,,,c8888888MMM##agaaaaaaaaawo, Gr.#MM888888ccccccccccc
,,,,,,,,,,,888MMMMMM###japP,gOPOorro# EwjMM8888888cccccccccc
,,,,,,,,,,,8MMMMMM####jawoJ EP ga#MMM888888cccccccccc
,,,,,,,,,,,MMMMMjjjjawgOQ8 Q wj#MMM888888cccccccccc
,,,,,,,,,,, gwaj#MMM888888cccccccccc
,,,,,,,,,,,MMMMMjjjjawgOQ8 Q wj#MMM888888cccccccccc
,,,,,,,,,,,8MMMMMM####jawoJ EP ga#MMM888888cccccccccc
,,,,,,,,,,,888MMMMMM###japP,gOPOorro# EwjMM8888888cccccccccc
,,,,,,,,,,,c8888888MMM##agaaaaaaaaawo, Gr.#MM888888ccccccccccc
,,,,,,,,,,,,c88888888888MM#######jjjwQg# ,aj#M888888cccccccccccc
,,,,,,,,,,,,cc8888888888888MMMM####jjagM Pa ,gQEPE#M888888ccccccccccccc
,,,,,,,,,,,,,cc88888888888888MMMMMM##jawwwwrpQ OprwjjjJ#MM88888cccccccccccccc
,,,,,,,,,,,,,,cc8888888888888888MMMMMMM##jjawQ Jwj####MM888888ccccccccccccccc
,,,,,,,,,,,,,,,ccc8888888888888888MMMMMMM###jwrG#owj##MMMM88888ccccccccccccccccc
,,,,,,,,,,,,,,,,ccccc8888888888888888MMMMMM##jaoro #MMMM8888cccccccccccccccccccc
,,,,,,,,,,,,,,,,,ccccccc8888888888888888MMMMM#.w##MMM8888ccccccccccccccccccccccc
,,,,,,,,,,,,,,,,,,,ccccccccc8888888888888888888888888ccccccccccccccccccccccccccc
,,,,,,,,,,,,,,,,,,,,ccccccccccccccc88888888888cccccccccccccccccccccccccccccccccc
,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccccccccccccccccccccccccccccccccccc,
,,,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccccccccccccccccccccccccccccccc,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccccccccccccccccccccccccc,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccccccccccccccccccccc,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccccccccccccc,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ccccccccccccccccccccccccc,,,,,,,,,,,,,,,,,

Undefined reference errror for cairo,h. How do you link it to a compiler?

I added cairo.h to run a image processing code. getting this error
ccmKP8Gv.o:flow.c:(.text+0x621): undefined reference to
`cairo_format_stride_for_width'
I think it is a linker-error, but I am not quite sure how to solve it.
Can anyone help?
Code
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <cairo.h>
#ifndef M_PI
#define M_PI 3.1415927
#endif
#define GR(X,Y) (d[(*s)*(Y)+bpp*(X)+((2)%bpp)])
#define GG(X,Y) (d[(*s)*(Y)+bpp*(X)+((1)%bpp)])
#define GB(X,Y) (d[(*s)*(Y)+bpp*(X)+((0)%bpp)])
#define SR(X,Y) (ht[4*tw*((Y)%th)+4*((X)%tw)+2])
#define SG(X,Y) (ht[4*tw*((Y)%th)+4*((X)%tw)+1])
#define SB(X,Y) (ht[4*tw*((Y)%th)+4*((X)%tw)+0])
#define RAD(A) (M_PI*((double)(A))/180.0)
uint8_t *houghtransform(uint8_t *d, int *w, int *h, int *s, int bpp)
{
int rho, theta, y, x, W = *w, H = *h;
int th = sqrt(W*W + H*H)/2.0;
int tw = 360;
uint8_t *ht = ( uint8_t*)malloc(th*tw*4);
memset(ht, 0, 4*th*tw); // black bg
for(rho = 0; rho < th; rho++)
{
for(theta = 0; theta < tw/*720*/; theta++)
{
double C = cos(RAD(theta));
double S = sin(RAD(theta));
uint32_t totalred = 0;
uint32_t totalgreen = 0;
uint32_t totalblue = 0;
uint32_t totalpix = 0;
if ( theta < 45 || (theta > 135 && theta < 225) || theta > 315) {
for(y = 0; y < H; y++) {
double dx = W/2.0 + (rho - (H/2.0-y)*S)/C;
if ( dx < 0 || dx >= W ) continue;
x = floor(dx+.5);
if (x == W) continue;
totalpix++;
totalred += GR(x, y);
totalgreen += GG(x, y);
totalblue += GB(x, y);
}
} else {
for(x = 0; x < W; x++) {
double dy = H/2.0 - (rho - (x - W/2.0)*C)/S;
if ( dy < 0 || dy >= H ) continue;
y = floor(dy+.5);
if (y == H) continue;
totalpix++;
totalred += GR(x, y);
totalgreen += GG(x, y);
totalblue += GB(x, y);
}
}
if ( totalpix > 0 ) {
double dp = totalpix;
SR(theta, rho) = (int)(totalred/dp) &0xff;
SG(theta, rho) = (int)(totalgreen/dp) &0xff;
SB(theta, rho) = (int)(totalblue/dp) &0xff;
}
}
}
*h = th; // sqrt(W*W+H*H)/2
*w = tw; // 360
*s = 4*tw;
return ht;
}
void image_process(char *rgb)
{
cairo_surface_t *inputimg = NULL;
cairo_surface_t *houghimg = NULL;
uint8_t *houghdata = NULL, *inputdata = NULL;
int w, h, s, bpp;
inputimg = cairo_image_surface_create_for_data((unsigned char*)rgb, CAIRO_FORMAT_RGB24, 320, 240, cairo_format_stride_for_width ( CAIRO_FORMAT_RGB24, 320));
w = cairo_image_surface_get_width(inputimg);
h = cairo_image_surface_get_height(inputimg);
s = cairo_image_surface_get_stride(inputimg);
bpp = cairo_image_surface_get_format(inputimg);
switch(bpp)
{
case CAIRO_FORMAT_ARGB32: bpp = 4; break;
case CAIRO_FORMAT_RGB24: bpp = 3; break;
case CAIRO_FORMAT_A8: bpp = 1; break;
default:
fprintf(stderr, "unsupported\n");
goto destroy;
}
inputdata = cairo_image_surface_get_data(inputimg);
houghdata = houghtransform(inputdata, &w, &h, &s, bpp);
printf("w=%d, h=%d\n", w, h);
houghimg = cairo_image_surface_create_for_data(houghdata,
CAIRO_FORMAT_RGB24,
w, h, s);
cairo_surface_write_to_png(houghimg, "hello.png");
destroy:
if (inputimg != NULL) cairo_surface_destroy(inputimg);
if (houghimg != NULL) cairo_surface_destroy(houghimg);
}
Make sure to compile with the -lcairo flag.
If you're using the command line on linux do it like so:
gcc -o main main.c -Wall -Wextra -lcairo
Or if you're using an IDE just add -lcairo to the linker options.

segment fault on programming 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.

Resources