Page 1 sur 1
Comment convertir une macro en C en PureBasic ?
Publié : dim. 06/nov./2005 20:04
par comtois
en fait c'est extrait d'un code en C++ , mais je ne crois pas que ça fasse de différence pour ce qui me concerne.
j'ai ce bout de code
Code : Tout sélectionner
typedef unsigned int uint32;
#define in(a) ((uint32&) a)
;Ici on calcul x,y et z , on obtient ainsi 3 nombres flottants
x.f=un calcul quelconque
y.f=un calcul quelconque
z.f=un calcul quelconque
;Et enfin on appelle la macro
Resultat.b = (( in(z)& ~(in(x) | in(y)) ) & 0x80000000)
Je sais que le compilo va remplacer la macro par le code qui lui correspond .
J'aurai au final
Code : Tout sélectionner
Resultat.b = (( ((uint32&) z)& ~(((uint32&) x) | ((uint32&) y)) ) & 0x80000000)
Déjà , est-ce que ça vous semble correct ?
Admettons que oui , alors maintenant j'expose mon problème , c'est qu'en fait je ne comprends pas ce que fait cette macro.
Si je comprends bien typedef permet de définir un type personnalisé.
En l'occurence il s'agirait ici d'un entier non signé.
le symbole & est utilisé pour donner l'adresse d'une variable.
en fait l'association uint32& permet de créer une référence ?
mais une référence sur quoi ?
est-ce que ça revient à écrire ça ?
Code : Tout sélectionner
Resultat.b = (((uint32 &z)& ~((uint32 &x) | ((uint32 &y)) & 0x80000000)
bon là j'avoue je suis paumé , si quelqu'un pouvait démêler la ficelle

Publié : dim. 06/nov./2005 20:19
par Chris
Ben déjà, "uint32" c'est le type "Unsigned Integer 32 bits", "Entier non signé 32 bits" donc, selon moi, tu peux le virer.
Par contre, le "&", c'est utilisé comment, en C++ ?
Publié : dim. 06/nov./2005 20:27
par Sami
Dans ce cas il me semble que le caractére & a deux utilisations. Dans le TypeDef c'est bien l'adresse de ta variable que tu stocke dans un entier de 32 bit non signé.
Par contre dans ton expression c'est l'opérateur Bitwise AND.
Plus d'infos sur la syntaxe du C/C++
ici
Publié : dim. 06/nov./2005 20:33
par comtois
c'est bon, je crois que j'ai compris
si j'ai
ça permet de manipuler i via ri.
c'est l'équivalent d'un pointeur sur i
alors finalement , ma macro revient à faire ça ?
Code : Tout sélectionner
Resultat.b = (((int(z))& ~((int(x)) | ((int(y)) & 0x80000000)
c'est trop simple, il doit y avoir encore un truc qui m'échappe !
Publié : dim. 06/nov./2005 23:31
par comtois
mouais c'est toujours pas clair .
je viens de lire un truc sur le transtypage en C:
apparemment en C++ c'est autrement , mais il est tard , et je ne vois pas d'exemple correspondant à mon cas, dans la doc que j'ai ça parle de transtypage dynamique, statique , de réinterprétation des données
bon ça ressemble à du transtypage mon affaire ?
pour passer d'une valeur en flottant à une valeur en entier non signé ?
c'est ça ?
Publié : lun. 07/nov./2005 11:14
par djes
Non, là, le casting ne sert que pour pouvoir faire les opérations booléennes, si je ne me trompe pas. En clair, il demande au compilateur de considérer les valeurs comme des valeurs entières, même si ce sont des flottants. Il n'y a pas de conversion! Le & sert effectivement à référencer la valeur en mémoire.
La macro effectue un certain nombre d'opérations booléennes directement sur les variables telles qu'elles sont en mémoire, sans conversion, rend négatif le signe, et met ça dans un octet (ça je comprends pas trop)
Je poste un exemple dès que possible.
Publié : lun. 07/nov./2005 12:04
par djes
Voilà, pour tester
Code : Tout sélectionner
x.f=-1
y.f=-1
Gosub test
x.f=-1
y.f=0
Gosub test
x.f=0
y.f=-1
Gosub test
x.f=0
y.f=1
Gosub test
x.f=1
y.f=0
Gosub test
x.f=1
y.f=1
Gosub test
End
test:
Debug "x : "+RSet(Hex(x),8,"0")+" ou "+StrF(x)
Debug "y : "+RSet(Hex(y),8,"0")+" ou "+StrF(y)
;Et enfin on appelle la macro
z=-1
Resultat.l = ( ( PeekL(@z) & ~( PeekL(@x) | PeekL(@y) ) ) & $80000000)
Resultat2.b=Resultat
Debug "z : "+RSet(Hex(z),8,"0")+" ou "+StrF(z,2)
Debug "Resultat : "+RSet(Hex(Resultat),8,"0")+" "+RSet(Hex(Resultat2),8,"0")
z=0
Resultat.l = ( ( PeekL(@z) & ~( PeekL(@x) | PeekL(@y) ) ) & $80000000)
Resultat2.b=Resultat
Debug "z : "+RSet(Hex(z),8,"0")+" ou "+StrF(z,2)
Debug "Resultat : "+RSet(Hex(Resultat),8,"0")+" "+RSet(Hex(Resultat2),8,"0")
z=1
Resultat.l = ( ( PeekL(@z) & ~( PeekL(@x) | PeekL(@y) ) ) & $80000000)
Resultat2.b=Resultat
Debug "z : "+RSet(Hex(z),8,"0")+" ou "+StrF(z,2)
Debug "Resultat : "+RSet(Hex(Resultat),8,"0")+" "+RSet(Hex(Resultat2),8,"0")
Debug ""
Return
End
Publié : lun. 07/nov./2005 12:31
par comtois
merci pour la réponse ,je regarderai ça ce soir , à tête reposée .
voila la fonction complète, le but c'est de déterminer si un point se trouve dans un triangle.J'avais fait une fonction pour ça , mais en 2D , faudrait que je la transforme un peu pour la 3D , et ensuite je voulais comparer la différence de vitesse entre la mienne et celle ci.
Below is a function that determines if a point is inside a triangle or not. This
is used in the collision detection step. Thanks to Keidy from Mr-Gamemaker
who posted this particular version of the function in a little competition we
held about who could post the fastest one.
Code : Tout sélectionner
typedef unsigned int uint32;
#define in(a) ((uint32&) a)
bool checkPointInTriangle(const VECTOR& point,
const VECTOR& pa,const VECTOR& pb, const VECTOR& pc)
{
VECTOR e10=pb-pa;
VECTOR e20=pc-pa;
float a = e10.dot(e10);
float b = e10.dot(e20);
float c = e20.dot(e20);
float ac_bb=(a*c)-(b*b);
VECTOR vp(point.x-pa.x, point.y-pa.y, point.z-pa.z);
float d = vp.dot(e10);
float e = vp.dot(e20);
float x = (d*c)-(e*b);
float y = (e*a)-(d*b);
float z = x+y-ac_bb;
return (( in(z)& ~(in(x)|in(y)) ) & 0x80000000);
}
Publié : lun. 07/nov./2005 12:37
par djes
Ok, c'est bien ça. Apparemment la macro renvoie TRUE (-1) si x et y sont positifs (>=0) et z négatif (<0).
Publié : lun. 07/nov./2005 19:01
par Sami
Attention le C et le C++ c'est trés différent même certains mots clef sont commun.
Publié : sam. 11/mars/2006 18:50
par comtois
Finalement je voulais à tout prix la tester cette procédure , alors je l'ai écrite comme ça :
Code : Tout sélectionner
Procedure TestPointDansTriangle1(*point.s_Vecteur, *pa.s_Vecteur, *pb.s_Vecteur, *pc.s_Vecteur)
Define.s_Vecteur e10, e20, vp
Define.f a, b, c, ac_bb, d, e, x, y, z
SoustractionVecteur(e10, *pb, *pa)
SoustractionVecteur(e20, *pc, *pa)
a = ProduitScalaire(e10, e10)
b = ProduitScalaire(e10, e20)
c = ProduitScalaire(e20, e20)
ac_bb = (a*c)-(b*b)
SoustractionVecteur(vp, *point, *pa)
d = ProduitScalaire(vp, e10)
e = ProduitScalaire(vp, e20)
x = (d*c)-(e*b)
y = (e*a)-(d*b)
z = x+y-ac_bb
ProcedureReturn ((PeekL(@z)& ~(PeekL(@x)|PeekL(@y))) & $80000000)
EndProcedure
ça fonctionne très bien , je n'ai pas encore vraiment comparé avec la procédure que j'utilisais , juste un test rapide ,et le gain serait de 20% environ.A confirmer cependant avec d'autres tests.
J'ai encore d'autres algos à tester, décidément ça prend du temps rien que pour calculer si un point se trouve dans un triangle !
PS :
Je ne comprends pas la nuance qu'il y a en C++ d'écrire
Ou
Moi je l'ai écrit exactement de la même manière, est-ce qu'il y a une subtilité qui m'échappe ?
[EDIT]
Tiens , je n'avais pas fait attention mais djes avait déjà donné la solution