Discussion:
Détourner un long double x86 pour une chaine de bits (was: Type long double)
(trop ancien pour répondre)
pehache
2021-06-13 08:46:35 UTC
Permalink
[snip]
cela rendrait le programme éminemment non portable, puisque
ces types flottants sur 80 bits ne sont absolument pas normalisés par les
langages (tels que C/C++ dont parle zeLittle) mais plutôt par certaines
architectures matérielles (de type x86, la première fois sur Intel 8087).
Certes, Microsoft considère les types 80-bit comme dépréciés pour son Win64
et donc dans son Visual C++ j'imagine, ce qui fait que Microsoft suggère
fortement
aux programmes de ne pas les utiliser, et qu'ils ont de très bonnes
raisons en interne.
Probablement parce que Windows a maintenant une déclinaison ARM,
architecture sur laquelle il n'y a pas de flottant 80 bits natif.
[snip] cela rendrait le programme éminemment non portable.
Je reviens là-dessus: quand on pense portabilité, on ne pense pas C en
premier, mais Java (ou mieux Lazarus me concernant, mais c'est loin
d'être un truc qui fait
"tilt" dans toutes les têtes, et en fait c'est pas plus mal), parce qu'il
faudra me montrer un code écrit en visual_C ou gnu_C qui tourne sous
Nunux \
freBSD \ Windows \ Androïd \ ARM, etc.: donc, c'est vraiment un argument
qui
fait plouf, là, avec du C pour étayer.
Le C est un langage normalisé ET de haut niveau, donc au contraire
totalement portable. Un code C qui respecte la norme peut être
compilé/exécuté partout où il y a un compilateur qui implémente la norme.

fu2 fr.comp.lang.c pour faire plaisir à OM ;)
--
"...sois ouvert aux idées des autres pour peu qu'elles aillent dans le
même sens que les tiennes.", ST sur fr.bio.medecine
Olivier Miakinen
2021-06-13 09:03:17 UTC
Permalink
Post by pehache
fu2 fr.comp.lang.c pour faire plaisir à OM ;)
C'est une bonne idée.

Or donc, le fil que zeLittle a déterré portait sur la possibilité d'utiliser
un type long double en C pour y manipuler des chaînes de bits de longueur plus
grande que 64, jusqu'à 80 bits.

Maintenant que nous sommes sur fr.comp.lang.c, et puisque visiblement ça semble
important à zeLittle au point qu'il soit revenu sur cette discussion, c'est le
lieu et le moment de nous montrer *vraiment* comment ça marche.

ZeLittle, c'est ton heure de gloire. Écris ici un bout de code en C montrant
comment :
- mettre le 72e bit à 1
- mettre le 79e bit à 0
- tester si le 75e bit vaut 1 ou 0

Cordialement,
--
Olivier Miakinen
Marc SCHAEFER
2021-06-13 10:45:31 UTC
Permalink
Post by Olivier Miakinen
- mettre le 72e bit à 1
- mettre le 79e bit à 0
- tester si le 75e bit vaut 1 ou 0
Sous OS POSIX, j'aurais tendance à abuser FD_SET pour ça, tant que cela
ne dépasse pas FD_SETSIZE.

fd_set toto; /* va prendre pas mal de place */

FD_ZERO(&toto);

FD_SET(72, &toto);

printf("%d\n", FD_ISSSET(75, &toto));

Pour faire des bitstrings de taille arbitraire en C, je n'ai rien trouvé
de standard. Une idée serait un tableau d'octets et des macros ou
fonctions qui du numéro de bit dérivent le numéro d'octet puis le masque
à appliquer.

Quant à appliquer cela sur un double de 64 bits, ça revient au même,
c'est un tableau de 8 octets. Je ne vois pas de raccourci.
Marc SCHAEFER
2021-06-13 10:50:35 UTC
Permalink
Post by Olivier Miakinen
- mettre le 72e bit à 1
- mettre le 79e bit à 0
- tester si le 75e bit vaut 1 ou 0
Sous OS POSIX, j'aurais tendance à abuser FD_SET pour ça, tant que cela
ne dépasse pas FD_SETSIZE.

fd_set toto; /* va prendre pas mal de place */

FD_ZERO(&toto);

FD_SET(72, &toto);

printf("%d\n", FD_ISSSET(75, &toto));

Pour faire des bitstrings de taille arbitraire en C, je n'ai rien trouvé
de standard. Une idée serait un tableau d'octets et des macros ou
fonctions qui du numéro de bit dérivent le numéro d'octet puis le masque
à appliquer.

Quant à appliquer cela sur un double de 64 bits ou un long double de 80
bits, ça revient au même, c'est un tableau de 8 octets, respectivement
10 octets. Je ne vois pas de raccourci.
Marc SCHAEFER
2021-06-13 10:56:03 UTC
Permalink
Post by Marc SCHAEFER
Sous OS POSIX, j'aurais tendance à abuser FD_SET pour ça, tant que cela
ne dépasse pas FD_SETSIZE.
En relisant la manpage, c'est trop abusif:

"Moreover, POSIX requires fd to be a valid file descriptor."

Donc reste la solution du flux d'octet maison?
pehache
2021-06-13 11:12:57 UTC
Permalink
Post by Marc SCHAEFER
Post by Olivier Miakinen
- mettre le 72e bit à 1
- mettre le 79e bit à 0
- tester si le 75e bit vaut 1 ou 0
Sous OS POSIX, j'aurais tendance à abuser FD_SET pour ça, tant que cela
ne dépasse pas FD_SETSIZE.
fd_set toto; /* va prendre pas mal de place */
FD_ZERO(&toto);
FD_SET(72, &toto);
printf("%d\n", FD_ISSSET(75, &toto));
Où est le "long double" là-dedans ?
--
"...sois ouvert aux idées des autres pour peu qu'elles aillent dans le
même sens que les tiennes.", ST sur fr.bio.medecine
Marc SCHAEFER
2021-06-13 11:38:52 UTC
Permalink
Post by pehache
Où est le "long double" là-dedans ?
Nul part. Cela permet d'émuler un entier jusqu'à 1024 bits sur la
plupart des plateforme 8 bits. Mais c'est de l'abus.

La solution à base de chaîne d'octet est plus générale.

A mon avis, utiliser un long double (10 octets) est plus compliqué que
10 octets. Et je ne verrais pas comment optimiser un long double plus
facilement qu'une suite d'octets.
Olivier Miakinen
2021-06-13 12:05:54 UTC
Permalink
Bonjour,
Post by Olivier Miakinen
- mettre le 72e bit à 1
- mettre le 79e bit à 0
- tester si le 75e bit vaut 1 ou 0
Sous OS POSIX, j'aurais tendance à [solutions normales]
Moi aussi. Mais tu n'as pas suivi la discussion qui a démarré hors
charte dans fr.sci.maths et fr.sci.physique. Il s'agissait d'un
troll(*) de zeLittle prétendant qu'un type 'long double' pourrait
être utile pour gérer des chaînes de bits jusqu'à 80 bits.


(*) Pour le moment c'est visiblement un troll puisque zeLittle a
sciemment exhumé cette discussion de junk vers les deux groupes où
elle était hors charte, mais sans jamais prouver ce qu'il prétendait.
Maintenant que nous sommes sur fr.comp.lang.c, c'est l'occasion pour
zeLittle de montrer qu'il ne trollait pas. Mais bien sûr je pense
qu'il n'en fera rien.
--
Olivier Miakinen
Marc SCHAEFER
2021-06-13 12:11:35 UTC
Permalink
Post by Olivier Miakinen
Moi aussi. Mais tu n'as pas suivi la discussion qui a démarré hors
charte dans fr.sci.maths et fr.sci.physique.
Effectivement, je n'ai pas suivi.
Post by Olivier Miakinen
Il s'agissait d'un troll(*) de zeLittle prétendant qu'un type 'long
double' pourrait être utile pour gérer des chaînes de bits jusqu'à 80
bits.
C'est juste, les 10 octets que cela représente permettent de le faire,
mais comme dit, je ne pense pas que c'est plus facile avec un long
double qu'avec un unsigned char[10].

Donc zeLittle a raison, mais cela ne fait pas avancer le schmilblick
pour autant.
Post by Olivier Miakinen
Maintenant que nous sommes sur fr.comp.lang.c, c'est l'occasion pour
zeLittle de montrer qu'il ne trollait pas. Mais bien sûr je pense
qu'il n'en fera rien.
Ou à la limite qu'elle montre les macros ou fonctions nécessaires pour
gérer un nombre de bits arbitraires, car ce n'est pas si difficile que
ça. Et qu'elle montre si c'est plus ou moins difficile avec unsigned
char[10] ou long double (à mon avis c'est de la même difficulté, avec
un typecast de plus).
pehache
2021-06-15 09:46:35 UTC
Permalink
Post by Marc SCHAEFER
Post by Olivier Miakinen
Moi aussi. Mais tu n'as pas suivi la discussion qui a démarré hors
charte dans fr.sci.maths et fr.sci.physique.
Effectivement, je n'ai pas suivi.
Post by Olivier Miakinen
Il s'agissait d'un troll(*) de zeLittle prétendant qu'un type 'long
double' pourrait être utile pour gérer des chaînes de bits jusqu'à 80
bits.
C'est juste, les 10 octets que cela représente permettent de le faire,
mais comme dit, je ne pense pas que c'est plus facile avec un long
double qu'avec un unsigned char[10].
Donc zeLittle a raison, mais cela ne fait pas avancer le schmilblick
pour autant.
Post by Olivier Miakinen
Maintenant que nous sommes sur fr.comp.lang.c, c'est l'occasion pour
zeLittle de montrer qu'il ne trollait pas. Mais bien sûr je pense
qu'il n'en fera rien.
Ou à la limite qu'elle montre les macros ou fonctions nécessaires pour
gérer un nombre de bits arbitraires, car ce n'est pas si difficile que
ça. Et qu'elle montre si c'est plus ou moins difficile avec unsigned
char[10] ou long double (à mon avis c'est de la même difficulté, avec
un typecast de plus).
Pour les types entiers (char compris) le C propose déjà les fonctions de
manipulations de bits individuels, ce qui n'est pas le cas pour les
types flottants. Donc ça va forcément être plus compliqué avec un "long
double" qu'avec un tableau de char.
--
"...sois ouvert aux idées des autres pour peu qu'elles aillent dans le
même sens que les tiennes.", ST sur fr.bio.medecine
Marc SCHAEFER
2021-06-15 12:46:11 UTC
Permalink
Post by pehache
Pour les types entiers (char compris) le C propose déjà les fonctions de
manipulations de bits individuels, ce qui n'est pas le cas pour les
types flottants. Donc ça va forcément être plus compliqué avec un "long
double" qu'avec un tableau de char.
Ce point spécifique se règle avec un seul typecast et prise d'adresse.
C'est du C, hein!

Mais je suis d'accord que c'est idiot.
pehache
2021-06-15 14:36:36 UTC
Permalink
Post by Marc SCHAEFER
Post by pehache
Pour les types entiers (char compris) le C propose déjà les fonctions de
manipulations de bits individuels, ce qui n'est pas le cas pour les
types flottants. Donc ça va forcément être plus compliqué avec un "long
double" qu'avec un tableau de char.
Ce point spécifique se règle avec un seul typecast et prise d'adresse.
C'est du C, hein!
Mais je suis d'accord que c'est idiot.
Je ne suis pas vraiment très habitué au C, je ne fais que bricoler...
Par curiosité tu écrirais ça comme ça ?

long double x;
char* cx;
cx = (char*)&x;

et ensuite accéder aux différents octect par c[i] ?
--
"...sois ouvert aux idées des autres pour peu qu'elles aillent dans le
même sens que les tiennes.", ST sur fr.bio.medecine
Marc SCHAEFER
2021-06-15 16:10:43 UTC
Permalink
Post by pehache
Je ne suis pas vraiment très habitué au C, je ne fais que bricoler...
J'en ai fait industriellement pendant 10 ans, récemment beaucoup moins.
Post by pehache
Par curiosité tu écrirais ça comme ça ?
long double x;
char* cx;
cx = (char*)&x;
et ensuite accéder aux différents octect par c[i] ?
Le principe est ainsi oui.

Voici le code pour un bitset générique avec des octets et un exemple
avec un float. Pas bien testé!

https://login.alphanet.ch/~schaefer/tmp/bitset.c
chmod a+rx bitset.c

Avec des macros ça pourrait être plus rapide.

Voici la sortie. L'assertion ratée à la fin c'est normal, on demande un
bit non représentable.

$ ./bitset.c
here a long double is: 16 bytes.
trying with: 0
byte 0 bit 0
byte 0 bit 0
bit value: 1
bytes: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 0 bit 0
byte 0 bit 0
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 1
byte 0 bit 1
byte 0 bit 1
bit value: 1
bytes: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 0 bit 1
byte 0 bit 1
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 2
byte 0 bit 2
byte 0 bit 2
bit value: 1
bytes: 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 0 bit 2
byte 0 bit 2
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 3
byte 0 bit 3
byte 0 bit 3
bit value: 1
bytes: 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 0 bit 3
byte 0 bit 3
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 4
byte 0 bit 4
byte 0 bit 4
bit value: 1
bytes: 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 0 bit 4
byte 0 bit 4
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 5
byte 0 bit 5
byte 0 bit 5
bit value: 1
bytes: 0x20 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 0 bit 5
byte 0 bit 5
trying with: 6
byte 0 bit 6
byte 0 bit 6
bit value: 1
bytes: 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 0 bit 6
byte 0 bit 6
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 7
byte 0 bit 7
byte 0 bit 7
bit value: 1
bytes: 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 0 bit 7
byte 0 bit 7
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 8
byte 1 bit 0
byte 1 bit 0
bit value: 1
bytes: 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 1 bit 0
byte 1 bit 0
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 15
byte 1 bit 7
byte 1 bit 7
bit value: 1
bytes: 0x00 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 1 bit 7
byte 1 bit 7
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 16
byte 2 bit 0
byte 2 bit 0
bit value: 1
bytes: 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 2 bit 0
byte 2 bit 0
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 42
byte 5 bit 2
byte 5 bit 2
bit value: 1
bytes: 0x00 0x00 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 5 bit 2
byte 5 bit 2
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 24
byte 3 bit 0
byte 3 bit 0
bit value: 1
bytes: 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
byte 3 bit 0
byte 3 bit 0
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00.
trying with: 127
byte 15 bit 7
byte 15 bit 7
bit value: 1
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80.
byte 15 bit 7
byte 15 bit 7
bit value: 0
bytes: 0x00 0x00 0x00 0x00 0x00 0x00 0xbitset: ./bitset.c:59: bit_assert: Assertion `bit_set(bit_number, value, bytes, size)' failed.
./bitset.c: line 3: 5242 Aborted ./$(basename $0 .c)
Continuer la lecture sur narkive:
Loading...