Bien entendu. Je ne peux l'ignorer, puisque c'est rappelé sur f.c.l.c
tous les deux ou trois jours.
J'ai pris soin d'écrire que ce code était défectueux - en C portable -,
et seulement en renvoi, j'ai signalé qu'il marchera dans "beaucoup de
cas". J'ai rapidement testé par acquit de conscience avec VC, 32bit et
64bit, et gcc 4.3.2, Ubuntu x86-64.
Je me demande quelles précautions oratoires faut-il prendre pour ne pas
provoquer ce genre de réponse. Peut-être écrire soi-même la réponse
dans le message, tant cette réponse est prévisible et était attendue?
Ou alors décider que ce petit truc assez amusant et qui ponctuellement
peut être pratique n'est pas digne d'intéresser quiconque sur f.c.l.c.
et le remettre dans sa culotte ?
Bien entendu. Je ne peux l'ignorer, puisque c'est rappelé sur f.c.l.c
tous les deux ou trois jours.
J'ai pris soin d'écrire que ce code était défectueux - en C portable -,
et seulement en renvoi, j'ai signalé qu'il marchera dans "beaucoup de
cas". J'ai rapidement testé par acquit de conscience avec VC, 32bit et
64bit, et gcc 4.3.2, Ubuntu x86-64.
Je me demande quelles précautions oratoires faut-il prendre pour ne pas
provoquer ce genre de réponse. Peut-être écrire soi-même la réponse
dans le message, tant cette réponse est prévisible et était attendue?
Ou alors décider que ce petit truc assez amusant et qui ponctuellement
peut être pratique n'est pas digne d'intéresser quiconque sur f.c.l.c.
et le remettre dans sa culotte ?
Bien entendu. Je ne peux l'ignorer, puisque c'est rappelé sur f.c.l.c
tous les deux ou trois jours.
J'ai pris soin d'écrire que ce code était défectueux - en C portable -,
et seulement en renvoi, j'ai signalé qu'il marchera dans "beaucoup de
cas". J'ai rapidement testé par acquit de conscience avec VC, 32bit et
64bit, et gcc 4.3.2, Ubuntu x86-64.
Je me demande quelles précautions oratoires faut-il prendre pour ne pas
provoquer ce genre de réponse. Peut-être écrire soi-même la réponse
dans le message, tant cette réponse est prévisible et était attendue?
Ou alors décider que ce petit truc assez amusant et qui ponctuellement
peut être pratique n'est pas digne d'intéresser quiconque sur f.c.l.c.
et le remettre dans sa culotte ?
Pour éviter cela, il suffit d'utiliser le type unsigned char.
En fait le probleme avec ce "classique" est qu'il ne fonctionne pas si a et b
sont la meme variable. La valeur est alors forcée à zero.
Une variante consiste à utiliser le ou exclusif:
#define SWAP(a, b) ((a)^=(b), (b)^=(a), (a)^=(b))
Notons aussi que ni l'un ni l'autre ne fonctionne pour des variables non
entières (float...)
Enfin il n'est pas prudent d'oublier les parenthèses extérieures dans
l'expansion de cette macro.
Pour éviter cela, il suffit d'utiliser le type unsigned char.
En fait le probleme avec ce "classique" est qu'il ne fonctionne pas si a et b
sont la meme variable. La valeur est alors forcée à zero.
Une variante consiste à utiliser le ou exclusif:
#define SWAP(a, b) ((a)^=(b), (b)^=(a), (a)^=(b))
Notons aussi que ni l'un ni l'autre ne fonctionne pour des variables non
entières (float...)
Enfin il n'est pas prudent d'oublier les parenthèses extérieures dans
l'expansion de cette macro.
Pour éviter cela, il suffit d'utiliser le type unsigned char.
En fait le probleme avec ce "classique" est qu'il ne fonctionne pas si a et b
sont la meme variable. La valeur est alors forcée à zero.
Une variante consiste à utiliser le ou exclusif:
#define SWAP(a, b) ((a)^=(b), (b)^=(a), (a)^=(b))
Notons aussi que ni l'un ni l'autre ne fonctionne pour des variables non
entières (float...)
Enfin il n'est pas prudent d'oublier les parenthèses extérieures dans
l'expansion de cette macro.
Pour éviter cela, il suffit d'utiliser le type unsigned char.
En fait le probleme avec ce "classique" est qu'il ne fonctionne pas si a et
b sont la meme variable. La valeur est alors forcée à zero.
Une variante consiste à utiliser le ou exclusif:
#define SWAP(a, b) ((a)^=(b), (b)^=(a), (a)^=(b))
Notons aussi que ni l'un ni l'autre ne fonctionne pour des variables non
entières (float...)
Enfin il n'est pas prudent d'oublier les parenthèses extérieures dans
l'expansion de cette macro.
Pour éviter cela, il suffit d'utiliser le type unsigned char.
En fait le probleme avec ce "classique" est qu'il ne fonctionne pas si a et
b sont la meme variable. La valeur est alors forcée à zero.
Une variante consiste à utiliser le ou exclusif:
#define SWAP(a, b) ((a)^=(b), (b)^=(a), (a)^=(b))
Notons aussi que ni l'un ni l'autre ne fonctionne pour des variables non
entières (float...)
Enfin il n'est pas prudent d'oublier les parenthèses extérieures dans
l'expansion de cette macro.
Pour éviter cela, il suffit d'utiliser le type unsigned char.
En fait le probleme avec ce "classique" est qu'il ne fonctionne pas si a et
b sont la meme variable. La valeur est alors forcée à zero.
Une variante consiste à utiliser le ou exclusif:
#define SWAP(a, b) ((a)^=(b), (b)^=(a), (a)^=(b))
Notons aussi que ni l'un ni l'autre ne fonctionne pour des variables non
entières (float...)
Enfin il n'est pas prudent d'oublier les parenthèses extérieures dans
l'expansion de cette macro.
Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
(*)Mais qui marchera dans "beaucoup de cas" même en cas d'overflow.
Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
(*)Mais qui marchera dans "beaucoup de cas" même en cas d'overflow.
Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
(*)Mais qui marchera dans "beaucoup de cas" même en cas d'overflow.
Pierre Maurette a écrit :
Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
Très joli et astucieux, je ne connaissais pas.
Grand classique ? ça dépend pour qui, peut-être qu'on fait ça en
assembleur mais je n'ai vu ça nulle part dans la littérature classique
du C (K&R, Harbison & Steele, Expert C programming, etc) ce qui ne fait
que me confirmer que la littérature C est mal faite.(*)Mais qui marchera dans "beaucoup de cas" même en cas d'overflow.
Mais c'est donc sans risque pour échanger des unsigned char ?
Pierre Maurette a écrit :
Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
Très joli et astucieux, je ne connaissais pas.
Grand classique ? ça dépend pour qui, peut-être qu'on fait ça en
assembleur mais je n'ai vu ça nulle part dans la littérature classique
du C (K&R, Harbison & Steele, Expert C programming, etc) ce qui ne fait
que me confirmer que la littérature C est mal faite.
(*)Mais qui marchera dans "beaucoup de cas" même en cas d'overflow.
Mais c'est donc sans risque pour échanger des unsigned char ?
Pierre Maurette a écrit :
Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
Très joli et astucieux, je ne connaissais pas.
Grand classique ? ça dépend pour qui, peut-être qu'on fait ça en
assembleur mais je n'ai vu ça nulle part dans la littérature classique
du C (K&R, Harbison & Steele, Expert C programming, etc) ce qui ne fait
que me confirmer que la littérature C est mal faite.(*)Mais qui marchera dans "beaucoup de cas" même en cas d'overflow.
Mais c'est donc sans risque pour échanger des unsigned char ?
Donc, si j'ai bien compris, plus efficace car qsort copiera alors des
adresses plutôt que des (éventuellement grosses) structures ?
Donc, si j'ai bien compris, plus efficace car qsort copiera alors des
adresses plutôt que des (éventuellement grosses) structures ?
Donc, si j'ai bien compris, plus efficace car qsort copiera alors des
adresses plutôt que des (éventuellement grosses) structures ?
ld a écrit :
Ton nom ld me disait quelque chose, ah! je viens de réaliser que tu es
Laurent Deniau.
> je n'appelle pas une variable, une zone tampon.
> static inline void
> swap(char *restrict a, char *restrict b, size_t s)
> {
> char t, *e = a+s;
> while (a < e) t=*a, *a++=b, *b++=t;
> }
OK, pour moi, tu utilises un tampon ... d'un caractère.
Au passage, je
ne connais pas vraiment inline (ni restrict) car je me cantonne à C90.
Ta façon de procéder n'est-elle pas très lente (sans inline donc)?
Est-il "académique" d'implémenter qsort sans tampon (avec ta méthod e) ?
(j'aime utiliser les procédés éprouvés, ça m'économise les ne urones ;) )
> Le quicksort que tu as montre n'est pas ce qui se fait de mieux, de
> loin.
Qu'est-ce qui du point de vue du codage C ne te parait pas convenable
dans l'implémentation de Plauger (je ne parle pas de l'algorithme, choi x
du pivot et toutes les optimisations de nature algorithmique qu'on
pourrait ajouter) ?
ld a écrit :
Ton nom ld me disait quelque chose, ah! je viens de réaliser que tu es
Laurent Deniau.
> je n'appelle pas une variable, une zone tampon.
> static inline void
> swap(char *restrict a, char *restrict b, size_t s)
> {
> char t, *e = a+s;
> while (a < e) t=*a, *a++=b, *b++=t;
> }
OK, pour moi, tu utilises un tampon ... d'un caractère.
Au passage, je
ne connais pas vraiment inline (ni restrict) car je me cantonne à C90.
Ta façon de procéder n'est-elle pas très lente (sans inline donc)?
Est-il "académique" d'implémenter qsort sans tampon (avec ta méthod e) ?
(j'aime utiliser les procédés éprouvés, ça m'économise les ne urones ;) )
> Le quicksort que tu as montre n'est pas ce qui se fait de mieux, de
> loin.
Qu'est-ce qui du point de vue du codage C ne te parait pas convenable
dans l'implémentation de Plauger (je ne parle pas de l'algorithme, choi x
du pivot et toutes les optimisations de nature algorithmique qu'on
pourrait ajouter) ?
ld a écrit :
Ton nom ld me disait quelque chose, ah! je viens de réaliser que tu es
Laurent Deniau.
> je n'appelle pas une variable, une zone tampon.
> static inline void
> swap(char *restrict a, char *restrict b, size_t s)
> {
> char t, *e = a+s;
> while (a < e) t=*a, *a++=b, *b++=t;
> }
OK, pour moi, tu utilises un tampon ... d'un caractère.
Au passage, je
ne connais pas vraiment inline (ni restrict) car je me cantonne à C90.
Ta façon de procéder n'est-elle pas très lente (sans inline donc)?
Est-il "académique" d'implémenter qsort sans tampon (avec ta méthod e) ?
(j'aime utiliser les procédés éprouvés, ça m'économise les ne urones ;) )
> Le quicksort que tu as montre n'est pas ce qui se fait de mieux, de
> loin.
Qu'est-ce qui du point de vue du codage C ne te parait pas convenable
dans l'implémentation de Plauger (je ne parle pas de l'algorithme, choi x
du pivot et toutes les optimisations de nature algorithmique qu'on
pourrait ajouter) ?
c'est la seule en l'absence de connaissance de l'alignement des
donnees. Il est possible pour des gros elements mal alignes (tres rare
en principe) de commencer avec des char* jusqu'au prochain alignement
d'un long* (< sizeof(long)), de continuer avec des long* et enfin de
finir avec des char* pour le dernier mot (< sizeof(long)).
Le plus simple reste tout de meme de faire ce que j'avais dit, c'est a
dire specialiser l'algo pour les trois cas: compatible long*, int* ou
char* comme ci-dessus (toujours ok).
en quoi c'est plus ou moins academique que le tampon? L'utilisation
d'un tampon pose des problemes que le swap n'a pas.
google "quicksort is optimal sedgwick" et tu verras un code beaucoup
plus lisible (et qui peut l'etre encore plus). sedgwick a fait sa
these sur le quicksort et ne cesse depuis d'essaye de l'ameliorer.
http://cos.cvs.sourceforge.net/viewvc/cos/CosStd/src/Array.c?revision=1.15&view=markup
bug au passage) et le code est beaucoup plus simple et court (la glibc
utilise un merge-sort et un quicksort seulement si elle n'a pas assez
de memoire pour le merge-sort).
c'est la seule en l'absence de connaissance de l'alignement des
donnees. Il est possible pour des gros elements mal alignes (tres rare
en principe) de commencer avec des char* jusqu'au prochain alignement
d'un long* (< sizeof(long)), de continuer avec des long* et enfin de
finir avec des char* pour le dernier mot (< sizeof(long)).
Le plus simple reste tout de meme de faire ce que j'avais dit, c'est a
dire specialiser l'algo pour les trois cas: compatible long*, int* ou
char* comme ci-dessus (toujours ok).
en quoi c'est plus ou moins academique que le tampon? L'utilisation
d'un tampon pose des problemes que le swap n'a pas.
google "quicksort is optimal sedgwick" et tu verras un code beaucoup
plus lisible (et qui peut l'etre encore plus). sedgwick a fait sa
these sur le quicksort et ne cesse depuis d'essaye de l'ameliorer.
http://cos.cvs.sourceforge.net/viewvc/cos/CosStd/src/Array.c?revision=1.15&view=markup
bug au passage) et le code est beaucoup plus simple et court (la glibc
utilise un merge-sort et un quicksort seulement si elle n'a pas assez
de memoire pour le merge-sort).
c'est la seule en l'absence de connaissance de l'alignement des
donnees. Il est possible pour des gros elements mal alignes (tres rare
en principe) de commencer avec des char* jusqu'au prochain alignement
d'un long* (< sizeof(long)), de continuer avec des long* et enfin de
finir avec des char* pour le dernier mot (< sizeof(long)).
Le plus simple reste tout de meme de faire ce que j'avais dit, c'est a
dire specialiser l'algo pour les trois cas: compatible long*, int* ou
char* comme ci-dessus (toujours ok).
en quoi c'est plus ou moins academique que le tampon? L'utilisation
d'un tampon pose des problemes que le swap n'a pas.
google "quicksort is optimal sedgwick" et tu verras un code beaucoup
plus lisible (et qui peut l'etre encore plus). sedgwick a fait sa
these sur le quicksort et ne cesse depuis d'essaye de l'ameliorer.
http://cos.cvs.sourceforge.net/viewvc/cos/CosStd/src/Array.c?revision=1.15&view=markup
bug au passage) et le code est beaucoup plus simple et court (la glibc
utilise un merge-sort et un quicksort seulement si elle n'a pas assez
de memoire pour le merge-sort).
Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
Un grand classique, pas exempt de défauts(*):
#define SWAPPE(a, b) (a)+=(b), (b)=(a)-(b), (a)-=(b)
>
Pour swapper deux variables de même type, il suffit de swapper leurs
représentations physiques, ce qu'on peut effectuer par le cast en type
unsigned. Soit deux variables d'un type quelconque et 'ent' le type
entier non signé de même taille.
>
Pour swapper deux variables de même type, il suffit de swapper leurs
représentations physiques, ce qu'on peut effectuer par le cast en type
unsigned. Soit deux variables d'un type quelconque et 'ent' le type
entier non signé de même taille.
>
Pour swapper deux variables de même type, il suffit de swapper leurs
représentations physiques, ce qu'on peut effectuer par le cast en type
unsigned. Soit deux variables d'un type quelconque et 'ent' le type
entier non signé de même taille.