BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019
-
28 févr. 2005 à 19:22
CriPpLe -
7 mars 2005 à 00:52
DWORD __fastcall Puiss2SupEgal_C(DWORD d)
{
DWORD r, n;
if(!d) return 0;
if(d & 1) d++;
r = 0x80000000;
n = d;
if(d & 0x80000000) goto verifInf;
do {
r >>= 1;
d <<= 1;
} while(!(d & 0x80000000));
verifInf:
if(r < n) r <<= 1;
if(!r) r = 0xFFFFFFFF;
return r;
}
Cette fonction retourne la plus proche puissance de 2 >= au param.
Si param == 0 doit retourner 0.
Si param > (2 puiss 31) doit retourner 0xFFFFFFFF;
Voila, je suis ouvert à toute proposition plus rapide, prog de test est fait.
Pas de table précalculée ni série de 32 'if' ou chose de ce genre pour cause de taille de code.
J'ai deja fait version ASM (dispo sur demande), est 6 fois + rapide que celle ci mais je voudrais savoir si vous avez des idées d'amélioration en C.
Toutes les propositions seront mesurées.
A vos claviers et merci de votre participation.
steve_clamage
Messages postés475Date d'inscriptiondimanche 3 octobre 2004StatutMembreDernière intervention11 août 20065 28 févr. 2005 à 22:35
Hylvenir, oui mais ca depend du jeu d'essai,
logiquement en dessous de 0x00010000 ca devrais etre plus rapide (plus
tant que le nombre tant vers 0, sur les petits nombres j'obtiens
jusqu'à x10) sinon c'est plus lent, dans ce sens une solution optimale
serais d'avoir deux lkt (une normale et une reverse) et tester si le
nombre est < 0x00010000.
BruNews, tu veux vraiment avoir une solution performante et peut couteuse en mémoire ? on doit souvent faire le choix, non ?
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 28 févr. 2005 à 22:43
non pas forcément, en calcul intensif on doit forcément passer par ASM.
Voila où j'en étais, je verrai si encore 1 ou 2 cycles trainent mais devrait pas y avoir plus.
Le truc c'est qu'il n'y a aucun bouclage:
__declspec(naked) DWORD __fastcall Puiss2SupEgal_ASM(DWORD d)
{
__asm {
mov eax, ecx
cmp eax, 1
jb short ramExit
ja short nbrOK
inc eax
nbrOK:
mov edx, eax
bsr ecx, eax
mov eax, 1
shl eax, cl
cmp eax, edx
jae short ramExit
shl eax, 1
jnz short ramExit
mov eax, -1
ramExit:
ret 0
}
}
en fait je m'étais gourré, le benf n'est que de 3 fois sur les grands calculs mais bon c'est déja ça.
cs_JCDjcd
Messages postés1138Date d'inscriptionmardi 10 juin 2003StatutMembreDernière intervention25 janvier 20094 1 mars 2005 à 10:34
Je suis aussi de dire que tout cela depend a la fois du test de comparaison (si n est uniforme alors repondre 31 a une probabilite de 0.5, repondre 30 de 0.25, ect ... alors que si c'est le resultat qui est aleatoire "genre 1<<random(0,31)" alors 31,30,...0 on 1/32 de probabilite de tomber) et de la taille des entiers consideres (32 bits ou 64 bits).
voici maintenant deux fonctions : la premiere de complexite O(log(n)) et la seconde de complexite O(log(log(n)))
typedef U32 TYPE;
#define N 32
/* si on veut tester en 64 bits
typedef U64 TYPE;
#define N 64
*/
//--------------------------------------------
TYPE MaxPow2_v1(TYPE n)
{
if(0 == n)
{
return 0;
}
else
{
int i = N;
while((((TYPE)1)<<(--i)) > n);
return i;
}
} // MaxPow2_v1()
//--------------------------------------------
TYPE MaxPow2_v2(TYPE n)
{
int i = 0;
int di = N>>1;
do
{
if(n >= (((TYPE)1) << (i+di)))
{
i += di;
}
}while((di >>= 1) > 0);
return i;
} // MaxPow2_v2()
la notation est mauvaise : les fonctions devraient etre nommees MinPow2, mais bon ...
La seconde methode consiste en une dichotomie sur la place du bit 1 le plus a gauche, d'ou on en deduit la complexite.
Pourquoi faire simple quand on peut faire compliqué ?
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 1 mars 2005 à 11:11
Salut,
je viens de mettre ici:
http://www.cppfrance.com/code.aspx?ID=29847 chacun pourra procéder aux tests directement et j'espère qu'on aura ainsi des trouvailles intéressantes, rien de tel que la forme 'concours' pour stimuler les neurones.