Trying to compile a source code in C

  • Context:
  • Thread starter Thread starter MathematicalPhysicist
  • Start date Start date
  • Tags Tags
    Code Source
Click For Summary

Discussion Overview

The discussion revolves around compiling a source code written in C, which simulates a billiard system. Participants explore various aspects of the code, including its structure, functionality, and potential issues that may arise during compilation or execution. The focus includes technical explanations and debugging related to the code's logic and syntax.

Discussion Character

  • Technical explanation
  • Debate/contested

Main Points Raised

  • Some participants point out potential issues with the use of the `main` function return type, suggesting it should return an `int` instead of `void`.
  • Others discuss the implications of using a negative seed for the random number generator, questioning whether this affects the randomness of the output.
  • A participant raises concerns about the array bounds for `data`, noting that it is initialized to `nbin`, but later used with `nb`, which may lead to out-of-bounds access.
  • Some participants propose adding error checking for user inputs to ensure valid values are provided, particularly for the number of points and bins.
  • There are discussions about the mathematical logic within the `billiard` function, with some participants suggesting that certain conditions may not cover all edge cases.
  • A later reply questions the efficiency of the algorithm, suggesting that there may be more optimal ways to implement the simulation.

Areas of Agreement / Disagreement

Participants express multiple competing views regarding the correctness of the code and its implementation. There is no consensus on the best approach to address the identified issues, and the discussion remains unresolved.

Contextual Notes

Limitations include the potential for undefined behavior due to array bounds and the lack of input validation. The discussion also highlights dependencies on specific assumptions about the input values and the random number generation process.

MathematicalPhysicist
Science Advisor
Gold Member
Messages
4,662
Reaction score
372
The source code is as follows:
C:
#include <stdio.h>
#include <math.h>
#define pi 3.14159265
#define nbin 10000
#define small 1.e-12
int addj(int data[nbin],double *tw,double x,double y,double vx,double vy, int xn,int j,double tc);
void billiard(int data[nbin],int nx,int nt,double x);
void bindist(int data[nbin], int nb, int nt);
int menue(void);
double ran1(long *idum);
void tabulate(int data[nbin], int nb, int rows);
void main(void)
{
    int c;            /* menue variable*/
    int col;        /*number of columns in table*/
    int data[nbin];         /* array of binned data*/
    int i;            /*dummy index*/
    long idum;        /*randum number generator seed*/
    int j;            /*dummy index*/
    int nb;            /*number of bins*/
    int nt;            /*number of data points collected*/
    int nx;            /*number of bins in x-direction*/
    double x;        /*initial x-coordinate, the initial
                y-coordinate is set to zero*/

    printf("input integer random number generator seed ");
    scanf("%d",&idum);
    idum=-idum;        /*random number generator is initialized
                by negative integer seed*/
    while((c=menue()) !=1)
    {
        switch (c)
        {
        case 2:    
            printf("input number of points nt ");
            scanf("%d",&nt);
            printf("input number of bins ");
            scanf("%d",&nb);
            for (i=0;i<nb;i++) data[i]=0;
            for(i=0;i<nt;i++)
                {
                j=ran1(&idum)*nb;
                data[j]++;
                }
            break;
        case 3:
            printf("sqrt of no of bins ");
            scanf("%d", &nx);
            nb=nx*nx;
            printf("input  0<x <1, or x<0 for random start ");
            scanf("%lf",&x);
            if (x<0) x=ran1(&idum);
            printf("input number of points nt ");
            scanf("%d",&nt);
            for(i=0;i<nb;i++)data[i]=0;
            billiard(data,nx,nt,x);
            break;           
        case 4:
            bindist(data,nb,nt);
            break;
        case 5:
            col=10;
            tabulate(data,nb,col);   
            break;
        }   
    }
}

int addj(int data[nbin],double *tw,double x,double y,double vx,double vy,int nx,int j, double tc)
    {
    int k;            /*column and bin number*/
    int l;            /*row number*/
    double xn;
    xn=((double)nx)-small;
    while (*tw>=1)
        {
        x+=(1.-tc)*vx;
        y+=(1-tc)*vy;
        *tw+=-1;
        tc=0;
        l=y*xn;
        k=x*xn;
        k+=l*nx;
    /*printf("x= %f, y= %f, k= %d, vx= %f,tw=%f \n",x,y,k,vx,*tw);*/
        data[k]++;
        j++;
        }
    return j;
    }

void billiard(int data[nbin],int nx,int nt,double x)
    {
    int i=0;            /*switch label*/
    int j=0;            /*time for next data point*/
    double tc;            /*current time*/
    double tw;                    /*time to hit the wall*/
    double xx;            /*temporary x-coordinate*/
    double y;            /*y-coordinate*/ 
    double yy;            /*temporary y-coordinate*/
    double vx;            /*magnitude of x-velocity*/
    double vy;            /*magnitude of y-velocity*/
    double vxm;            /* -vx*/
    double vym;            /* -vy*/
    printf("x-initial= %f\n",x);
    printf("input vx>0 ");
    scanf("%lf",&vx);
    printf("input vy>0 ");
    scanf("%lf",&vy);
    vxm=-vx;
    vym=-vy;
    tw=y=0;
    while (j<nt)
        {
        tc=tw;
        /*printf("i=%d\n",i);*/
        switch (i)
            {
            case 0:     /* 0<x<1,y=0, xspeed >0, y speed >0 */
                yy=(1.-x)*vy/vx;
                if (yy<1.)
                    {
                    tw+=yy/vy;
                    i=1;
                    j=addj(data,&tw,x,y,vx,vy,nx,j,tc);
                    x=1.;
                    y=yy;
                    }
                else
                    {
                    tw+=1./vy;
                    i=6;
                    j=addj(data,&tw,x,y,vx,vy,nx,j,tc);
                    x+=vx/vy;
                    y=1;
                    }                                   
                break;
            case 1:     /* x=1,0<y=1;xspeed <0, yspeed >0 */
                xx=1.-(1.-y)*vx/vy;
                if (xx>0)
                    {
                    tw+=(1.-xx)/vx;
                    i=2;
                    j=addj(data,&tw,x,y,vxm,vy,nx,j,tc);
                    y=1;
                    x=xx;
                    }
                else
                    {
                    tw+=1./vx;
                    i=7;
                    j=addj(data,&tw,x,y,vxm,vy,nx,j,tc);
                    x=0;
                    y+=vy/vx;
                    }
                break;
            case 2:        /* 0<x<1,y=1, xspeed <0, y speed <0 */
                yy=1-x*vy/vx;
                if (yy>0)
                    {
                    tw+=(1.-yy)/vy;
                    i=3;
                    j=addj(data,&tw,x,y,vxm,vym,nx,j,tc);
                    x=0.;
                    y=yy;
                    }
                else
                    {
                    tw+=1./vy;
                    i=4;
                    j=addj(data,&tw,x,y,vxm,vym,nx,j,tc);
                    x+=-vx/vy;
                    y=0;
                    }                                   
                break;
            case 3:     /* x=0,0<y=1;xspeed >0, yspeed <0 */
                xx=y*vx/vy;
                if (xx<1)
                    {
                    tw+=xx/vx;
                    i=0;
                    j=addj(data,&tw,x,y,vx,vym,nx,j,tc);
                    y=0;
                    x=xx;
                    }
                else
                    {
                    tw+=1./vx;
                    i=5;
                    j=addj(data,&tw,x,y,vx,vym,nx,j,tc);
                    x=1;
                    y+=-vy/vx;
                    }
                break;
            case 4:     /* 0<x<1,y=0, xspeed <0, y speed >0 */
                yy=x*vy/vx;
                if (yy<1)
                    {
                    tw+=yy/vy;
                    i=7;
                    j=addj(data,&tw,x,y,vxm,vy,nx,j,tc);
                    x=0.;
                    y=yy;
                    }
                else
                    {
                    tw+=1./vy;
                    i=2;
                    j=addj(data,&tw,x,y,vxm,vy,nx,j,tc);
                    x+=-vx/vy;
                    y=1;
                    }                                   
                break;
            case 5:     /* x=1,0<y=1;xspeed <0, yspeed <0 */
                xx=1.-y*vx/vy;
                if (xx>0)
                    {
                    tw+=(1.-xx)/vx;
                    i=4;
                    j=addj(data,&tw,x,y,vxm,vym,nx,j,tc);
                    y=0;
                    x=xx;
                    }
                else
                    {
                    tw+=1./vx;
                    i=3;
                    j=addj(data,&tw,x,y,vxm,vym,nx,j,tc);
                    x=0;
                    y+=-vy/vx;
                    }
                break;
            case 6:        /* 0<x<1,y=1, xspeed >0, y speed <0 */
                yy=1.-(1.-x)*vy/vx;
                if (yy>0)
                    {
                    tw+=(1.-yy)/vy;
                    i=5;
                    j=addj(data,&tw,x,y,vx,vym,nx,j,tc);
                    x=1.;
                    y=yy;
                    }
                else
                    {
                    tw+=1./vy;
                    i=0;
                    j=addj(data,&tw,x,y,vx,vym,nx,j,tc);
                    x+=vx/vy;
                    y=0;
                    }                                    
                break;
            case 7:     /* x=0,0<y=1;xspeed <0, yspeed >0 */
                xx=(1.-y)*vx/vy;
                if (xx<1)
                    {
                    tw+=xx/vx;
                    i=6;
                    j=addj(data,&tw,x,y,vx,vy,nx,j,tc);
                    y=1;
                    x=xx;
                    }
                else
                    {
                    tw+=1./vx;
                    i=1;
                    j=addj(data,&tw,x,y,vx,vy,nx,j,tc);
                    x=1;
                    y+=vy/vx;
                    }
                break;
            }
        }
    }           
/* This routine checks if deviation of number of elements in each bin follows a Gaussian distribution*/
void bindist(int data[nbin], int n, int nt)
    {
    double ave, adev, sdev, var, skew, curt;
    int j;
    double x,y,s=0,p,a,b,c;   
        x=(double) n;
    y=(double) nt;
    if (n <= 0) printf("nb must be at least 1 in moment\n");
    for (j=0;j<n;j++) s += data[j];
    ave=s/n;
    adev=var=skew=curt=0.0;
    for (j=0;j<n;j++) 
        {
        adev += fabs(s=data[j]-ave);
        var += (p=s*s);
        skew += (p *= s);
        curt += (p *= s);
        }
    adev /= x;
    var /=x;
    sdev=sqrt(var);
    if (var)
        {
        skew /= n*var*sdev;
        curt=curt/(n*var*var)-3.0;
        }
    printf("%39s %11s\n\n","calculated","expected");
    a=y/x;
    printf("%s %17s %12.4f %12.4f\n","Mean :"," ",ave,a);
    c=sqrt(2.*a/pi);
    printf("%s %4s %12.4f %12.4f\n","Average Deviation :"," ",adev,c);
    b=sqrt(a);
    printf("%s %3s %12.4f %12.4f\n","Standard Deviation :"," ",sdev,b);   
    printf("%s %13s %12.4f %12.4f\n","Variance :"," ",var,a);
    printf("%s %13s %12.4f %12.4f\n","Skewness :"," ",skew,0.0);
    printf("%s %13s %12.4f %12.4f\n","Kurtosis :"," ",curt,0);
    }

/* to generate menue*/
int menue()
    {
    int x;
    printf("1 to quit \n");
    printf("2 to generate random distribution of points\n");
    printf("3 to generate billiard distribution of points \n");
    printf("4 to analyze data\n");
    printf("5 to tabulate data\n");
    scanf("%d", &x);
    return x;
    }

/* modified version of ran1 of numerical recipies. NOTE the initial seed should be NEGATIVE!*/
#define IA 16807
#define IM 2147483647
#define AM (1.0/IM)
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)
double ran1(long *idum)
{
    int j;
    long k;
    static long iy=0;
    static long iv[NTAB];
    double temp;

    if (*idum <= 0 || !iy) {
        if (-(*idum) < 1) *idum=1;
        else *idum = -(*idum);
        for (j=NTAB+7;j>=0;j--) {
            k=(*idum)/IQ;
            *idum=IA*(*idum-k*IQ)-IR*k;
            if (*idum < 0) *idum += IM;
            if (j < NTAB) iv[j] = *idum;
        }
        iy=iv[0];
    }
    k=(*idum)/IQ;
    *idum=IA*(*idum-k*IQ)-IR*k;
    if (*idum < 0) *idum += IM;
    j=iy/NDIV;
    iy=iv[j];
    iv[j] =*idum;
    if((temp=AM*iy)>RNMX)return RNMX;
    else return temp;
}
#undef IA
#undef IM
#undef AM
#undef IQ
#undef IR
#undef NTAB
#undef NDIV
#undef EPS
#undef RNMX

/* to tabulate an integer array, nb is total number of entries,
co is number of columns*/
void tabulate(int data[nbin], int nb, int co)
    {
    int i,j,k,x, y;
    x=nb/co;
    y=nb%co;
    k=0;
    for (i=0;i<x;i++)
        {
        for (j=0;j<co;j++)
            {
            printf("%6d",data[k]);
            k++;
            }
        printf("\n");
        }
    for (i=0;i<y;i++)
        {
        printf("%6d",data[k]);
        k++;
        }
    printf("\n");
    }

I tried this webpage here:
https://www.tutorialspoint.com/compile_c_online.php

to compile and execute the source code (I didn't write this file, I got it from someone);

I get the following errors:
sh-4.2$ gcc -o main *.c
/tmp/cc42VpoO.o: In function `bindist':
main.c:(.text+0x1308): undefined reference to `sqrt'
main.c:(.text+0x1400): undefined reference to `sqrt'
main.c:(.text+0x146a): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
sh-4.2$ main
sh: main: command not found

Isn't the sqrt operation defined in the library of math?

How to fix this code so that it will run appropriately?, btw it's a bit dated from the nineties of the 20th century. :-)

Thanks.
 
Technology news on Phys.org
Try compiling with the -lm option:

gcc -lm -o exe_file src_file.c


MathematicalPhysicist said:
Isn't the sqrt operation defined in the library of math?

No. The math.h header file only contains (among other things) a function prototype which declares that sqrt is a function and that it accepts a double-precision floating-point number as an argument and produces a double-precision floating-point number as its result. It doesn't contain the definition (i.e., the code) of the sqrt function. That is normally already compiled and stored in a library somewhere, and you need to tell the compiler explicitly to link against that library. That is what the -lm switch does for gcc.
 
wle said:
Try compiling with the -lm option:

gcc -lm -o exe_file src_file.c

No. The math.h header file only contains (among other things) a function prototype which declares that sqrt is a function and that it accepts a double-precision floating-point number as an argument and produces a double-precision floating-point number as its result. It doesn't contain the definition (i.e., the code) of the sqrt function. That is normally already compiled and stored in a library somewhere, and you need to tell the compiler explicitly to link against that library. That is what the -lm switch does for gcc.

I typed in the sh line:
Code:
gcc -lm -o exe_file main.c
and after that executed the code, but got the error:
Code:
main: command not found

Why doesn't it seem to work, is it because the code is old? has C changed drastically since the nineties?! I don't think so.
 
MathematicalPhysicist said:
I typed in the sh line:
Code:
gcc -lm -o exe_file main.c
and after that executed the code, but got the error:
Code:
main: command not found

Why doesn't it seem to work, is it because the code is old?

No*. You called the wrong program name. The "-o exe_file" part of the command tells gcc to compile the program into an executable file called "exe_file". You should replace "exe_file" with whatever program name you like. Assuming the source code is in the file "main.c", if you literally want the program to be called "main" then you should do
Code:
$ gcc -lm -o main main.c
$ ./main
to compile and run the file ('$' here represents the prompt -- don't type that). The "./" tells the shell to look in the current directory for the program.

The -o switch is optional. If you omit it, gcc will use the default program name "a.out":
Code:
$ gcc -lm main.c
$ ./a.out
----------

*Not that this looks like particularly correct C code, for that matter. void main(void) is strictly speaking wrong, though C compilers will often compile it anyway.
 
Last edited:
OK, thanks @wle it works.
 
You could have run the program without recompiling, by using the command

Code:
$ ./exe_file

In fact, I bet you probably still have that file lying around, unless you deleted it explicitly with the rm command!
 

Similar threads

Replies
1
Views
2K
Replies
1
Views
3K
  • · Replies 4 ·
Replies
4
Views
3K
  • · Replies 4 ·
Replies
4
Views
2K
  • · Replies 22 ·
Replies
22
Views
4K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 7 ·
Replies
7
Views
2K
  • · Replies 22 ·
Replies
22
Views
3K
  • · Replies 36 ·
2
Replies
36
Views
6K
  • · Replies 2 ·
Replies
2
Views
3K