Decalages d'un nombre de bits pouvant etre >= a la taille du type
134 réponses
Vincent Lefevre
J'ai besoin de faire un décalage vers la droite sur un type entier
(disons non signé) générique (i.e. défini par typedef) d'un certain
nombre constant de bits. Le problème est que ce nombre de bits peut
être supérieur ou égal à la taille du type en question. Une idée
sur la façon de faire ça efficacement sans obtenir de comportement
indéfini et sans passer par un outil du style "configure"?
J'ai besoin de faire un décalage vers la droite sur un type entier (disons non signé) générique (i.e. défini par typedef) d'un certain nombre constant de bits. Le problème est que ce nombre de bits peut être supérieur ou égal à la taille du type en question. Une idée sur la façon de faire ça efficacement sans obtenir de comportement indéfini et sans passer par un outil du style "configure"?
ne te convient pas? Si le compilateur n'est pas trop con, il va simplifier cela comme il faut pour des decalages constants, sinon est-ce que sa qualite ne serait pas telle que l'optimisation manquante est de toute maniere sans objet?
OK, on suppose qu'il n'y a pas de bits de padding dans les entiers non signes. C'est quoi encore la derniere machine avec une telle caracteristique? La lisp-machine?
A+
-- Jean-Marc FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc Site de usenet-fr: http://www.usenet-fr.news.eu.org
Vincent Lefevre <vincent+news@vinc17.org> writes:
J'ai besoin de faire un décalage vers la droite sur un type entier
(disons non signé) générique (i.e. défini par typedef) d'un certain
nombre constant de bits. Le problème est que ce nombre de bits peut
être supérieur ou égal à la taille du type en question. Une idée
sur la façon de faire ça efficacement sans obtenir de comportement
indéfini et sans passer par un outil du style "configure"?
ne te convient pas? Si le compilateur n'est pas trop con, il va
simplifier cela comme il faut pour des decalages constants, sinon
est-ce que sa qualite ne serait pas telle que l'optimisation manquante
est de toute maniere sans objet?
OK, on suppose qu'il n'y a pas de bits de padding dans les entiers non
signes. C'est quoi encore la derniere machine avec une telle
caracteristique? La lisp-machine?
A+
--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org
J'ai besoin de faire un décalage vers la droite sur un type entier (disons non signé) générique (i.e. défini par typedef) d'un certain nombre constant de bits. Le problème est que ce nombre de bits peut être supérieur ou égal à la taille du type en question. Une idée sur la façon de faire ça efficacement sans obtenir de comportement indéfini et sans passer par un outil du style "configure"?
ne te convient pas? Si le compilateur n'est pas trop con, il va simplifier cela comme il faut pour des decalages constants, sinon est-ce que sa qualite ne serait pas telle que l'optimisation manquante est de toute maniere sans objet?
OK, on suppose qu'il n'y a pas de bits de padding dans les entiers non signes. C'est quoi encore la derniere machine avec une telle caracteristique? La lisp-machine?
A+
-- Jean-Marc FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc Site de usenet-fr: http://www.usenet-fr.news.eu.org
Laurent Deniau
Jean-Marc Bourguet wrote:
Vincent Lefevre <vincent+ writes:
J'ai besoin de faire un décalage vers la droite sur un type entier (disons non signé) générique (i.e. défini par typedef) d'un certain nombre constant de bits. Le problème est que ce nombre de bits peut être supérieur ou égal à la taille du type en question. Une idée sur la façon de faire ça efficacement sans obtenir de comportement indéfini et sans passer par un outil du style "configure"?
le nom peut preter a confusion, SAFE_RSHIFT conviendrait mieux non?
Ceci dit, comme je l'ai dit dans mon post precedent, tu aura quand meme un warning du compilo (GCC: warning: right shift count >= width of type). C'est pour ca que l'on utilise generalement les UXXX_MAX et les directives du preprocesseur pour selectionner le code qui va bien.
a+, ld.
Jean-Marc Bourguet wrote:
Vincent Lefevre <vincent+news@vinc17.org> writes:
J'ai besoin de faire un décalage vers la droite sur un type entier
(disons non signé) générique (i.e. défini par typedef) d'un certain
nombre constant de bits. Le problème est que ce nombre de bits peut
être supérieur ou égal à la taille du type en question. Une idée
sur la façon de faire ça efficacement sans obtenir de comportement
indéfini et sans passer par un outil du style "configure"?
le nom peut preter a confusion, SAFE_RSHIFT conviendrait mieux non?
Ceci dit, comme je l'ai dit dans mon post precedent, tu aura quand meme
un warning du compilo (GCC: warning: right shift count >= width of
type). C'est pour ca que l'on utilise generalement les UXXX_MAX et les
directives du preprocesseur pour selectionner le code qui va bien.
J'ai besoin de faire un décalage vers la droite sur un type entier (disons non signé) générique (i.e. défini par typedef) d'un certain nombre constant de bits. Le problème est que ce nombre de bits peut être supérieur ou égal à la taille du type en question. Une idée sur la façon de faire ça efficacement sans obtenir de comportement indéfini et sans passer par un outil du style "configure"?
le nom peut preter a confusion, SAFE_RSHIFT conviendrait mieux non?
Ceci dit, comme je l'ai dit dans mon post precedent, tu aura quand meme un warning du compilo (GCC: warning: right shift count >= width of type). C'est pour ca que l'on utilise generalement les UXXX_MAX et les directives du preprocesseur pour selectionner le code qui va bien.
a+, ld.
Vincent Lefevre
Dans l'article <cju8hj$dnm$, Laurent Deniau écrit:
Au passage, tu ne nous as toujours pas explique pourquoi tu tiens absolument a faire les decalages?
J'accepte tout code équivalent.
unsigned long U = T;
if (ULONG_MAX == 4294967295UL && GMP_LIMB_BITS > 31) { U = 0; } else { U >>= GMP_LIMB_BITS; }
T = U
est quand meme plus simple et defini.
Non, pas si GMP_LIMB_BITS est supérieur à la taille d'un unsigned long.
J'ai besoin de faire un décalage vers la droite sur un type entier (disons non signé) générique (i.e. défini par typedef) d'un certain nombre constant de bits. Le problème est que ce nombre de bits peut être supérieur ou égal à la taille du type en question. Une idée sur la façon de faire ça efficacement sans obtenir de comportement indéfini et sans passer par un outil du style "configure"?
OK, on suppose qu'il n'y a pas de bits de padding dans les entiers non signes. C'est quoi encore la derniere machine avec une telle caracteristique? La lisp-machine?
Si cela n'a pas d'importance, pourquoi ça n'a pas été supprimé de la norme alors?
Dans l'article <pxbis9p5kyz.fsf@news.bourguet.org>,
Jean-Marc Bourguet <jm@bourguet.org> écrit:
Vincent Lefevre <vincent+news@vinc17.org> writes:
J'ai besoin de faire un décalage vers la droite sur un type entier
(disons non signé) générique (i.e. défini par typedef) d'un certain
nombre constant de bits. Le problème est que ce nombre de bits peut
être supérieur ou égal à la taille du type en question. Une idée
sur la façon de faire ça efficacement sans obtenir de comportement
indéfini et sans passer par un outil du style "configure"?
OK, on suppose qu'il n'y a pas de bits de padding dans les entiers
non signes. C'est quoi encore la derniere machine avec une telle
caracteristique? La lisp-machine?
Si cela n'a pas d'importance, pourquoi ça n'a pas été supprimé de la
norme alors?
J'ai besoin de faire un décalage vers la droite sur un type entier (disons non signé) générique (i.e. défini par typedef) d'un certain nombre constant de bits. Le problème est que ce nombre de bits peut être supérieur ou égal à la taille du type en question. Une idée sur la façon de faire ça efficacement sans obtenir de comportement indéfini et sans passer par un outil du style "configure"?
OK, on suppose qu'il n'y a pas de bits de padding dans les entiers non signes. C'est quoi encore la derniere machine avec une telle caracteristique? La lisp-machine?
Si cela n'a pas d'importance, pourquoi ça n'a pas été supprimé de la norme alors?
C'est les bits de padding qui te genent ou il y a qqch que je n'ai pas vu?
OK, on suppose qu'il n'y a pas de bits de padding dans les entiers non signes. C'est quoi encore la derniere machine avec une telle caracteristique? La lisp-machine?
Si cela n'a pas d'importance, pourquoi ça n'a pas été supprimé de la norme alors?
J'etais pas la, je ne peux donc te donner que des suppositions qui vont de personne n'a trouve le probleme suffisemment important pour en faire une proposition formelle a il y a une machine repandue que je ne connais pas sur laquelle cela pose un probleme.
La norme est un moyen, pas une fin.
A+
-- Jean-Marc FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc Site de usenet-fr: http://www.usenet-fr.news.eu.org
C'est les bits de padding qui te genent ou il y a qqch que je n'ai pas
vu?
OK, on suppose qu'il n'y a pas de bits de padding dans les entiers
non signes. C'est quoi encore la derniere machine avec une telle
caracteristique? La lisp-machine?
Si cela n'a pas d'importance, pourquoi ça n'a pas été supprimé de la
norme alors?
J'etais pas la, je ne peux donc te donner que des suppositions qui
vont de personne n'a trouve le probleme suffisemment important pour en
faire une proposition formelle a il y a une machine repandue que je ne
connais pas sur laquelle cela pose un probleme.
La norme est un moyen, pas une fin.
A+
--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org
C'est les bits de padding qui te genent ou il y a qqch que je n'ai pas vu?
OK, on suppose qu'il n'y a pas de bits de padding dans les entiers non signes. C'est quoi encore la derniere machine avec une telle caracteristique? La lisp-machine?
Si cela n'a pas d'importance, pourquoi ça n'a pas été supprimé de la norme alors?
J'etais pas la, je ne peux donc te donner que des suppositions qui vont de personne n'a trouve le probleme suffisemment important pour en faire une proposition formelle a il y a une machine repandue que je ne connais pas sur laquelle cela pose un probleme.
La norme est un moyen, pas une fin.
A+
-- Jean-Marc FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc Site de usenet-fr: http://www.usenet-fr.news.eu.org
Laurent Deniau
Vincent Lefevre wrote:
Dans l'article <cju8hj$dnm$, Laurent Deniau écrit:
Au passage, tu ne nous as toujours pas explique pourquoi tu tiens absolument a faire les decalages?
J'accepte tout code équivalent.
unsigned long U = T;
if (ULONG_MAX == 4294967295UL && GMP_LIMB_BITS > 31) { U = 0; } else { U >>= GMP_LIMB_BITS; }
T = U
est quand meme plus simple et defini.
Non, pas si GMP_LIMB_BITS est supérieur à la taille d'un unsigned long.
Defini dans tous les cas mais ne fait pas necessairement ce que tu veux en >32 bits d'ou ma suggestion initiale de passer par le preprocesseur pour selectionner le code correct. Idem pour le warning du compilo.
Le probleme n'est pas si GMP_LIMB_BITS shift plus que la taille d'un unsigned long mais si le type de T est superieur la taille d'un unsigned long.
Si tu ne trouves toujours pas, je te posterais le code.
a+, ld.
Vincent Lefevre wrote:
Dans l'article <cju8hj$dnm$1@sunnews.cern.ch>,
Laurent Deniau <Laurent.Deniau@cern.ch> écrit:
Au passage, tu ne nous as toujours pas explique pourquoi tu tiens
absolument a faire les decalages?
J'accepte tout code équivalent.
unsigned long U = T;
if (ULONG_MAX == 4294967295UL && GMP_LIMB_BITS > 31) {
U = 0;
} else {
U >>= GMP_LIMB_BITS;
}
T = U
est quand meme plus simple et defini.
Non, pas si GMP_LIMB_BITS est supérieur à la taille d'un unsigned long.
Defini dans tous les cas mais ne fait pas necessairement ce que tu veux
en >32 bits d'ou ma suggestion initiale de passer par le preprocesseur
pour selectionner le code correct. Idem pour le warning du compilo.
Le probleme n'est pas si GMP_LIMB_BITS shift plus que la taille d'un
unsigned long mais si le type de T est superieur la taille d'un unsigned
long.
Si tu ne trouves toujours pas, je te posterais le code.
Dans l'article <cju8hj$dnm$, Laurent Deniau écrit:
Au passage, tu ne nous as toujours pas explique pourquoi tu tiens absolument a faire les decalages?
J'accepte tout code équivalent.
unsigned long U = T;
if (ULONG_MAX == 4294967295UL && GMP_LIMB_BITS > 31) { U = 0; } else { U >>= GMP_LIMB_BITS; }
T = U
est quand meme plus simple et defini.
Non, pas si GMP_LIMB_BITS est supérieur à la taille d'un unsigned long.
Defini dans tous les cas mais ne fait pas necessairement ce que tu veux en >32 bits d'ou ma suggestion initiale de passer par le preprocesseur pour selectionner le code correct. Idem pour le warning du compilo.
Le probleme n'est pas si GMP_LIMB_BITS shift plus que la taille d'un unsigned long mais si le type de T est superieur la taille d'un unsigned long.
Si tu ne trouves toujours pas, je te posterais le code.
a+, ld.
Vincent Lefevre
Dans l'article <cjucbf$lub$, Laurent Deniau écrit:
Defini dans tous les cas mais ne fait pas necessairement ce que tu veux en >32 bits d'ou ma suggestion initiale de passer par le preprocesseur pour selectionner le code correct. Idem pour le warning du compilo.
Non, la norme dit bien que c'est du comportement indéfini.
6.5.7 Bitwise shift operators [...] [#3] The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
Dans l'article <cjucbf$lub$1@sunnews.cern.ch>,
Laurent Deniau <Laurent.Deniau@cern.ch> écrit:
Defini dans tous les cas mais ne fait pas necessairement ce que tu veux
en >32 bits d'ou ma suggestion initiale de passer par le preprocesseur
pour selectionner le code correct. Idem pour le warning du compilo.
Non, la norme dit bien que c'est du comportement indéfini.
6.5.7 Bitwise shift operators
[...]
[#3] The integer promotions are performed on each of the
operands. The type of the result is that of the promoted
left operand. If the value of the right operand is negative
or is greater than or equal to the width of the promoted
left operand, the behavior is undefined.
Dans l'article <cjucbf$lub$, Laurent Deniau écrit:
Defini dans tous les cas mais ne fait pas necessairement ce que tu veux en >32 bits d'ou ma suggestion initiale de passer par le preprocesseur pour selectionner le code correct. Idem pour le warning du compilo.
Non, la norme dit bien que c'est du comportement indéfini.
6.5.7 Bitwise shift operators [...] [#3] The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
C'est les bits de padding qui te genent ou il y a qqch que je n'ai pas vu?
Non, c'est le 6.5.7#3.
J'etais pas la, je ne peux donc te donner que des suppositions qui vont de personne n'a trouve le probleme suffisemment important pour en faire une proposition formelle a il y a une machine repandue que je ne connais pas sur laquelle cela pose un probleme.
La norme est un moyen, pas une fin.
Tu fais ce que tu veux. En ce qui me concerne, je n'ai pas du tout envie de revoir mon code dès qu'une nouvelle machine apparaît.
C'est les bits de padding qui te genent ou il y a qqch que je n'ai pas
vu?
Non, c'est le 6.5.7#3.
J'etais pas la, je ne peux donc te donner que des suppositions qui
vont de personne n'a trouve le probleme suffisemment important pour en
faire une proposition formelle a il y a une machine repandue que je ne
connais pas sur laquelle cela pose un probleme.
La norme est un moyen, pas une fin.
Tu fais ce que tu veux. En ce qui me concerne, je n'ai pas du tout
envie de revoir mon code dès qu'une nouvelle machine apparaît.
C'est les bits de padding qui te genent ou il y a qqch que je n'ai pas vu?
Non, c'est le 6.5.7#3.
J'etais pas la, je ne peux donc te donner que des suppositions qui vont de personne n'a trouve le probleme suffisemment important pour en faire une proposition formelle a il y a une machine repandue que je ne connais pas sur laquelle cela pose un probleme.
La norme est un moyen, pas une fin.
Tu fais ce que tu veux. En ce qui me concerne, je n'ai pas du tout envie de revoir mon code dès qu'une nouvelle machine apparaît.
a plusieurs inconvénients : - la comparaison est faite à l'envers, ce qui est facile à corriger ;-) - c est instancié deux fois. - on a potentiellement un comportement indéfini sur une partie de l'expression. - on a un warning stupide dans ce cas si c est constant et que le compilateur se croit malin. - on peut aussi avoir un warning si c est une expression d'un type signé à cause de la comparaison signé/non-signé - le code généré est inefficace si c est une expression non constante (2 jump)
On peut remédier à ces inconvénients comme ceci: - on utilise une fonction inline au lieu d'une macro, mais cela force le type de v, ce qui n'est pas forcement loisible - on peut masquer c dans le shift, ce qui supprime le warning sans changer le code pour les valeurs constantes de c, mais ralentit un peu les instances ou c est non constante, à moins que le compilo soit très fort et que l'architecture s'y prete. On peut aussi utiliser 2 macros differentes pour les shifts constants et calculés. - on caste (c) en (unsigned) - on peut faire une expression sans test, ce qui generera un meilleur code si le compilo est subtil.
Exemples:
// code avec jmp: #define SAFE_SHR(v, c) ((sizeof(v) * CHAR_BIT < (unsigned)(c)) ? 0 : (v) >> ((c) & (sizeof(v) * CHAR_BIT - 1))) // code sans jmp pour les valeurs constantes ou non constantes: #define SAFE_SHR(v, c) (-(sizeof(v) * CHAR_BIT < (unsigned)(c)) & ((v) >> ((c) & (sizeof(v) * CHAR_BIT - 1)))
On peut supprimer le masquage dans la version non constante si un shift d'une quantité trop grande ne déclenche pas d'exception. On devrait caster (c) en (unsigned) dans la comparaison pour éviter un warning potentiel sur la comparaison d'un signé et d'un non-signé. Pour ceux qui ont un doute sur la facon de supprimer le jump, on peut aussi écrire cela, mais c'est encore moins lisible: . #define SAFE_SHR(v, c) ((((int)c - (int)sizeof(v) * CHAR_BIT) >> (sizeof(int) * CHAR_BIT - 1)) & ((v) >> ((c) & ((sizeof(v) * CHAR_BIT) - 1)))
Ceci suppose que le shift signé duplique le bit de signe. Donc à n'utiliser que sur les architectures où cette supposition est valide Un bon gros commentaire sera indispensable pour expliquer ce que font ces macros !
Vite une aspirine !
Chqrlie.
PS: je trouve regrettable que le shift d'une quantité *constante* supérieure à la taille du type non soit pas défini avec la sémantique évidente, mais je suppose que c'est pour préserver la cohérence et l'efficacité de l'implémentation.
a plusieurs inconvénients :
- la comparaison est faite à l'envers, ce qui est facile à corriger ;-)
- c est instancié deux fois.
- on a potentiellement un comportement indéfini sur une partie de
l'expression.
- on a un warning stupide dans ce cas si c est constant et que le
compilateur se croit malin.
- on peut aussi avoir un warning si c est une expression d'un type signé à
cause de la comparaison signé/non-signé
- le code généré est inefficace si c est une expression non constante (2
jump)
On peut remédier à ces inconvénients comme ceci:
- on utilise une fonction inline au lieu d'une macro, mais cela force le
type de v, ce qui n'est pas forcement loisible
- on peut masquer c dans le shift, ce qui supprime le warning sans changer
le code pour les valeurs constantes de c, mais ralentit un peu les instances
ou c est non constante, à moins que le compilo soit très fort et que
l'architecture s'y prete. On peut aussi utiliser 2 macros differentes pour
les shifts constants et calculés.
- on caste (c) en (unsigned)
- on peut faire une expression sans test, ce qui generera un meilleur code
si le compilo est subtil.
Exemples:
// code avec jmp:
#define SAFE_SHR(v, c) ((sizeof(v) * CHAR_BIT < (unsigned)(c)) ? 0 : (v) >>
((c) & (sizeof(v) * CHAR_BIT - 1)))
// code sans jmp pour les valeurs constantes ou non constantes:
#define SAFE_SHR(v, c) (-(sizeof(v) * CHAR_BIT < (unsigned)(c)) & ((v) >>
((c) & (sizeof(v) * CHAR_BIT - 1)))
On peut supprimer le masquage dans la version non constante si un shift
d'une quantité trop grande ne déclenche pas d'exception.
On devrait caster (c) en (unsigned) dans la comparaison pour éviter un
warning potentiel sur la comparaison d'un signé et d'un non-signé.
Pour ceux qui ont un doute sur la facon de supprimer le jump, on peut aussi
écrire cela, mais c'est encore moins lisible: .
#define SAFE_SHR(v, c) ((((int)c - (int)sizeof(v) * CHAR_BIT) >>
(sizeof(int) * CHAR_BIT - 1)) & ((v) >> ((c) & ((sizeof(v) * CHAR_BIT) -
1)))
Ceci suppose que le shift signé duplique le bit de signe. Donc à n'utiliser
que sur les architectures où cette supposition est valide
Un bon gros commentaire sera indispensable pour expliquer ce que font ces
macros !
Vite une aspirine !
Chqrlie.
PS: je trouve regrettable que le shift d'une quantité *constante* supérieure
à la taille du type non soit pas défini avec la sémantique évidente, mais je
suppose que c'est pour préserver la cohérence et l'efficacité de
l'implémentation.
a plusieurs inconvénients : - la comparaison est faite à l'envers, ce qui est facile à corriger ;-) - c est instancié deux fois. - on a potentiellement un comportement indéfini sur une partie de l'expression. - on a un warning stupide dans ce cas si c est constant et que le compilateur se croit malin. - on peut aussi avoir un warning si c est une expression d'un type signé à cause de la comparaison signé/non-signé - le code généré est inefficace si c est une expression non constante (2 jump)
On peut remédier à ces inconvénients comme ceci: - on utilise une fonction inline au lieu d'une macro, mais cela force le type de v, ce qui n'est pas forcement loisible - on peut masquer c dans le shift, ce qui supprime le warning sans changer le code pour les valeurs constantes de c, mais ralentit un peu les instances ou c est non constante, à moins que le compilo soit très fort et que l'architecture s'y prete. On peut aussi utiliser 2 macros differentes pour les shifts constants et calculés. - on caste (c) en (unsigned) - on peut faire une expression sans test, ce qui generera un meilleur code si le compilo est subtil.
Exemples:
// code avec jmp: #define SAFE_SHR(v, c) ((sizeof(v) * CHAR_BIT < (unsigned)(c)) ? 0 : (v) >> ((c) & (sizeof(v) * CHAR_BIT - 1))) // code sans jmp pour les valeurs constantes ou non constantes: #define SAFE_SHR(v, c) (-(sizeof(v) * CHAR_BIT < (unsigned)(c)) & ((v) >> ((c) & (sizeof(v) * CHAR_BIT - 1)))
On peut supprimer le masquage dans la version non constante si un shift d'une quantité trop grande ne déclenche pas d'exception. On devrait caster (c) en (unsigned) dans la comparaison pour éviter un warning potentiel sur la comparaison d'un signé et d'un non-signé. Pour ceux qui ont un doute sur la facon de supprimer le jump, on peut aussi écrire cela, mais c'est encore moins lisible: . #define SAFE_SHR(v, c) ((((int)c - (int)sizeof(v) * CHAR_BIT) >> (sizeof(int) * CHAR_BIT - 1)) & ((v) >> ((c) & ((sizeof(v) * CHAR_BIT) - 1)))
Ceci suppose que le shift signé duplique le bit de signe. Donc à n'utiliser que sur les architectures où cette supposition est valide Un bon gros commentaire sera indispensable pour expliquer ce que font ces macros !
Vite une aspirine !
Chqrlie.
PS: je trouve regrettable que le shift d'une quantité *constante* supérieure à la taille du type non soit pas défini avec la sémantique évidente, mais je suppose que c'est pour préserver la cohérence et l'efficacité de l'implémentation.