Trying to compile a source code in C

  • Thread starter Thread starter MathematicalPhysicist
  • Start date Start date
  • Tags Tags
    Code Source
AI Thread Summary
The discussion centers around issues encountered while compiling and executing a C program that uses mathematical functions, specifically the `sqrt` function from the math library. Users faced errors indicating undefined references to `sqrt`, which is resolved by using the `-lm` option during compilation to link the math library. There was confusion regarding the command to run the compiled program, as users initially attempted to execute the program without specifying the correct output file name. The correct command involves using `gcc -lm -o main main.c` to compile and then `./main` to run the executable. Additionally, it was noted that the code uses `void main(void)`, which is not standard in C, although many compilers accept it. The conversation highlights the importance of linking libraries correctly and understanding command-line syntax for compiling and executing C programs.
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!
 
Dear Peeps I have posted a few questions about programing on this sectio of the PF forum. I want to ask you veterans how you folks learn program in assembly and about computer architecture for the x86 family. In addition to finish learning C, I am also reading the book From bits to Gates to C and Beyond. In the book, it uses the mini LC3 assembly language. I also have books on assembly programming and computer architecture. The few famous ones i have are Computer Organization and...
I have a quick questions. I am going through a book on C programming on my own. Afterwards, I plan to go through something call data structures and algorithms on my own also in C. I also need to learn C++, Matlab and for personal interest Haskell. For the two topic of data structures and algorithms, I understand there are standard ones across all programming languages. After learning it through C, what would be the biggest issue when trying to implement the same data...

Similar threads

Replies
4
Views
2K
Replies
22
Views
3K
Replies
1
Views
2K
Replies
7
Views
2K
Replies
2
Views
3K
Replies
22
Views
3K
Back
Top