Witam
Napisałem program w c używając Dev-C++.
(kod na końcu).
Pod windows działa bez problemu.
Ponieważ ( naiwnie) sądziłem że będzie wieloplatformowy
więc sprawdziłem kompilację pod linuksem.
Niestety otrzymałem komunikato o błędach :
================
adam@acer:~/c/f_arg$ gcc main.c
main.c: In function ‘Give_E_Argument_F’:
main.c:74: warning: incompatible implicit declaration of built-in
function ‘atan2’
main.c:98: warning: incompatible implicit declaration of built-in
function ‘floor’
main.c: In function ‘main’:
main.c:254: warning: incompatible implicit declaration of built-in
function ‘fabs’
/tmp/cca3BONX.o: In function `Give_E_Argument_F':
main.c:(.text+0x17a): undefined reference to `atan2'
main.c:(.text+0x29f): undefined reference to `atan2'
main.c:(.text+0x320): undefined reference to `floor'
collect2: ld returned 1 exit status
=======================================
(Szukałem w googlu)
Jak to rozwiązać ?
Adam
===kod===
#include <stdio.h>
#include <stdlib.h> /* for ISO C Random Number Functions */
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
int GiveLastIteration(double Zx, double Zy,double Cx ,double Cy , int
iter_max, double bailout2)
{
// z= x+ y*i
long double x ,y ;
//
long double u, v;
int iter; // iteration
iter=0;//there was no iteration
y =Zy;
x =Zx;
u = x*x ;
v = y*y;
if ( u + v > bailout2 ) return iter; // point is in target set =no
need to iterate
//
do
{
// Fc(z)= z*z +c
y = 2 * x * y + Cy;
x = u - v + Cx;
u = x*x;
v = y*y;
iter+=1;
}
while (( u + v <= bailout2 ) && iter<iter_max) ;
return iter;
}
//------------ function Give_E_Argument_F
----------------------------------------------
// This function computes external argument of point C in turns
// for filled-in Julia set for Fc(z)= z*z + c
// external argument = Arg(Phi(c))
// 1 [turn] = 360 [degrees] = 2* M_PI [radians]
//
// output is a principal value of external argument
// 0 <= Give_E_Argument_F < 1
//
// it is only for points z that are escaping ( going to infinity ) !!!!!!
//
// this function is based on cpp function mndlbrot::turn()
// in the file mndlbrot.cpp in mandelXXsrc.zip .
// from program mandel by Wolf Jung
// http://www.mndynamics.com/indexp.html
// The function arg(z/(z-c)) is discontinuous on the straight line
segment from the critical point z = 0
// to the critical value z = c, which is drawn in red in the figure:
when z belongs to this line segment,
// then z/(z-c) will be on the negative real axis.
double Give_E_Argument_F(double Zx, double Zy,double Cx ,double Cy)
{
int j;
double
s = 1,
dr = 1.0/2,
theta, // external angle
// t=u+v*i
u, v,
r,
x = Zx, y = Zy;
if (x*x + y*y < 1e-8) return 8; //prevent atan2(0,0) if disconnected
// Arg(Phi(c))= Arg(c)+ ...
theta = atan2(y, x);
for (j = 1; j < 100; j++)
{
s *= dr;
// z=Fc(z)
double temp = x*x - y*y + Cx;
y = 2*x*y + Cy;
x = temp;
//t=z-c = u+v*i
u = x - Cx;
v = y - Cy;
//
r = x*x + y*y;
if (r < .0001) return -7; //?
//
theta += s * atan2(u*y - v*x, u*x + v*y);
//
if (r/s > 1e25) break;
}
//
if (r < 1000) return -6;
//
theta *= (.5/M_PI);
//
theta -= floor(theta);
return theta;
}//f_turn
void GiveRainbowColor(double position,unsigned char c[])
{
/* if position > 1 then we have repetition of colors
it maybe useful */
if (position>1.0){if (position-(int)position==0.0)position=1.0; else
position=position-(int)position;}
unsigned char nmax=6; /* number of color bars */
double m=nmax* position;
int n=(int)m; // integer of m
double f=m-n; // fraction of m
unsigned char t=(int)(f*255);
switch( n){
case 0: {
c[0] = 255;
c[1] = t;
c[2] = 0;
break;
};
case 1: {
c[0] = 255 - t;
c[1] = 255;
c[2] = 0;
break;
};
case 2: {
c[0] = 0;
c[1] = 255;
c[2] = t;
break;
};
case 3: {
c[0] = 0;
c[1] = 255 - t;
c[2] = 255;
break;
};
case 4: {
c[0] = t;
c[1] = 0;
c[2] = 255;
break;
};
case 5: {
c[0] = 255;
c[1] = 0;
c[2] = 255 - t;
break;
};
default: {
c[0] = 255;
c[1] = 0;
c[2] = 0;
break;
};
}; // case
}
int main()
{
const double Cx=0,//-0.11,
Cy=1;//0.65569999;
/* screen coordinate = coordinate of pixels */
int iX, iY,
iXmin=0, iXmax=2000,
iYmin=0, iYmax=2000,
iWidth=iXmax-iXmin+1,
iHeight=iYmax-iYmin+1,
/* 3D data : X , Y, color */
/* number of bytes = number of pixels of image * number of
bytes of color */
iLength=iWidth*iHeight*3,/* 3 bytes of color */
index; /* of array */
int iXinc, iYinc;
/* world ( double) coordinate = parameter plane*/
const double ZxMin=-2.5;
const double ZxMax=2.5;
const double ZyMin=-2.5;
const double ZyMax=2.5;
/* */
double PixelWidth=(ZxMax-ZxMin)/iWidth;
double PixelHeight=(ZyMax-ZyMin)/iHeight;
double Zx, Zy, /* Z=Zx+Zy*i */
Zx2,Zy2,
ER=400.0,ER2=ER*ER,
argument;
/* */
int Iteration,
LastIteration;
const int IterationMax=1000;
/* PPM file */
FILE * fp;
char *filename="f_i_100.ppm";
char *comment="# this is julia set for c=i ";/* comment should
start with # */
const int MaxColorComponentValue=255;/* color component ( R or G or
B) is coded from 0 to 255 */
unsigned char color[3];
/* dynamic 1D array for 24-bit color values */
unsigned char *array;
int a_index;
/*-------------------------------------------------------------------*/
array = malloc( iLength * sizeof(unsigned char) );
if (array == NULL)
{
fprintf(stderr,"Could not allocate memory");
getchar();
return 1;
}
else
{
fprintf(stderr,"I'm working, wait a while\n");
/* fill the data array with white points */
for(index=0;index<iLength-1;++index) array[index]=0;
/* ---------------------------------------------------------------*/
for(iY=0;iY<iYmax;++iY)
for(iX=0;iX<iXmax;++iX)
{
Zy=ZyMin + iY*PixelHeight; /* Y axis */
if (fabs(Zy)<PixelHeight/2) Zy=0.0; /* */
/* initial value of orbit Z0 */
Zx=ZxMin + iX*PixelWidth;
LastIteration=GiveLastIteration(Zx, Zy, Cx , Cy ,
IterationMax, ER2);
a_index=((iYmax-iY-1)*iXmax+iX)*3;
if (LastIteration==IterationMax)
{ // interior of Julia set
/* plot pixel */
array[a_index]=0; //red
array[a_index+1]=0;//green
array[a_index+2]=0; //blue
}
else
{ // exterior of Julia set
argument= Give_E_Argument_F( Zx, Zy, Cx , Cy);
if ((int)(argument*100)%2==0)argument=1-argument;
GiveRainbowColor(argument,color);
/* plot pixel */
array[a_index]=color[0];
array[a_index+1]=color[1];
array[a_index+2]=color[2];
} // if (LastIteration==IterationMax
/* check the orientation of Z-plane */
/* mark first quadrant of cartesian plane*/
// if (Zx>0 && Zy>0)
// { /* plot pixel */
//
// array[a_index]=255; //red
// array[a_index+1]=0;
// array[a_index+2]=0;
// }
}//for(iX=0;iX<iXmax;++iX)
/* write the whole data array to ppm file in one step */
/*create new file,give it a name and open it in binary mode */
fp= fopen(filename,"wb"); /* b - binary mode */
if (fp == NULL){ fprintf(stderr,"file error"); }
else
{
/*write ASCII header to the file*/
fprintf(fp,"P6\n %s\n %d\n %d\n
%d\n",comment,iXmax,iYmax,MaxColorComponentValue);
/*write image data bytes to the file*/
fwrite(array,iLength ,1,fp);
fclose(fp);
fprintf(stderr,"OK : file "); fprintf(stderr,filename);
fprintf(stderr," saved.\nDone !!!");
getchar();
}
free(array);
return 0;
} // if (array == NULL)
} // int main()
> adam@acer:~/c/f_arg$ gcc main.c
gcc main.c -lm
I dodaj #include <math.h>
> pod linuxem też,
U mnie nie. ( bez wprowadzałem zmian zaproponowanych
przez Marcina , ponieważ wydaje mi się że to jest jakby osobny wątek)
Taki sam komunikat o błędach mam też od innej osoby.
>sprawdz jakie biblioteki masz pod dev-c++
Chodzi o biblioteki dołączne w opcjach programu ?
( tam nie mam żadnych )
Poniżej jest mój makefile.win:
Te zapisy o QT to widoczne ślad gdy chciałem
używać dev-C++ do QT.
Może to ma znaczenie ?
Adam
================makefile.win====
# Project: Project1
# Makefile created by Dev-C++ 4.9.9.2
CPP = g++.exe
CC = gcc.exe
WINDRES = windres.exe
RES =
OBJ = main.o $(RES)
LINKOBJ = main.o $(RES)
LIBS = -L"C:/MinGW/lib" -L"C:/Dev-Cpp/include" -L"C:/Qt/4.3.4/include"
INCS = -I"C:/MinGW/include" -I"C:/Qt/4.3.1/include"
CXXINCS = -I"C:/Dev-Cpp/include" -I"C:/Qt/4.3.4/include"
-I"C:/Qt/4.3.4/include/Qt" -I"C:/Qt/4.3.4/include/Qt3Support"
-I"C:/Qt/4.3.4/include/QtAssistant" -I"C:/Qt/4.3.4/include/QtCore"
-I"C:/Qt/4.3.4/include/QtDBus" -I"C:/Qt/4.3.4/include/QtDesigner"
-I"C:/Qt/4.3.4/include/QtGui" -I"C:/Qt/4.3.4/include/QtNetwork"
-I"C:/Qt/4.3.4/include/QtOpenGL" -I"C:/Qt/4.3.4/include/QtScript"
-I"C:/Qt/4.3.4/include/QtSql" -I"C:/Qt/4.3.4/include/QtSvg"
-I"C:/Qt/4.3.4/include/QtTest" -I"C:/Qt/4.3.4/include/QtUiTools"
-I"C:/Qt/4.3.4/include/QtXml"
BIN = Project1.exe
CXXFLAGS = $(CXXINCS)
CFLAGS = $(INCS)
RM = rm -f
.PHONY: all all-before all-after clean clean-custom
all: all-before Project1.exe all-after
clean: clean-custom
${RM} $(OBJ) $(BIN)
$(BIN): $(OBJ)
$(CC) $(LINKOBJ) -o "Project1.exe" $(LIBS)
main.o: main.c
$(CC) -c main.c -o main.o $(CFLAGS)
===============================================
Wielkie dzięki. (:-))
1. Czy to znaczy że pod windows kompilator znajdował
sam ( gdzieś) inną bibliotekę z deklaracjami tych funkcji ?
2. Co oznacza opcja -lm ?
( szukałem w dokumentacji gcc ale bez efektu )
Adam
> 1. Czy to znaczy że pod windows kompilator znajdował
> sam ( gdzieś) inną bibliotekę z deklaracjami tych funkcji ?
Pod Windows te funkcje są w tej samej bibliotece, co standardowe
funkcje C. Pod Uniksami są w osobnej bibliotece.
Natomiast jeśli chodzi o #include, to być może w danym kompilatorze
pod Windows stdio.h albo stdlib.h włącza math.h, stąd brak jawnego
włączania math.h nie jest wykrywany.
> 2. Co oznacza opcja -lm ?
> ( szukałem w dokumentacji gcc ale bez efektu )
Ta opcja jest przekazywana linkerowi: man ld
Oznacza: dołącz bibliotekę o nazwie libm.
"For example, the C math library is typically stored in the file
‘/usr/lib/libm.a’ on Unix-like systems. The corresponding prototype
declarations for the functions in this library are given in the header
file ‘/usr/include/math.h"
"Należy zwr—ócić uwagę na regułę nadawania bibliotekom nazw. Nakazuje
ona, by nazwa bibioteki miała posta ć libident.a, gdzie pole ident
może mie ć długość od 1 do 7 znak—w. W linii wywołania kompilatora, po
opcji -l, podawana jest tylko część ident
zamiast całej nazwy biblioteki, np.: -lm dla biblioteki libm.a."
O to chodziło ?
Adam
> "For example, the C math library is typically stored in the file
> '/usr/lib/libm.a' on Unix-like systems. The corresponding prototype
> declarations for the functions in this library are given in the header
> file '/usr/include/math.h"
Trochę to się zdezaktualizowało: pod Linuksem zazwyczaj używane są
biblioteki ładowane dynamicznie (/lib/libm-*.so z symlinkami /lib/
libm.so.* i /usr/lib/libm.so). Opcja -lm używa libm.so albo libm.a w
zależności od tego, które są znalezione, i w zależności od obecności
opcji -static. Inne Uniksy mają chyba podobnie (z innymi konwencjami
nazw i innymi formatami bibliotek; lib*.dylib w MacOS X).
> "Należy zwrócić uwagę na regułę nadawania bibliotekom nazw. Nakazuje
> ona, by nazwa bibioteki miała postać libident.a, gdzie pole ident
> może mieć długość od 1 do 7 znaków.
Ciekawe, który to prehistoryczny system miał taki limit. Pod Linuksem
nazwy bibliotek bywają dłuższe.
Adam
To co się dowiedziałem umieściłem :
http://pl.wikibooks.org/wiki/C/Przeno%C5%9Bno%C5%9B%C4%87_program%C3%B3w#Biblioteczne_problemy
Mam nadzieję że dobrze (?)
Pozdrawiam
Adam