Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

opérations avec GMP

9 réponses
Avatar
mpg
Bonjour,

J'écris un peu de code manipulant des grands nombres, et j'utilise pour cela
la bibliothèque GNU MP. ( http://www.gnu.org/software/gmp/manual/ )

Une chose que je n'arrive pas à deviner en lisant la doc, c'est si une
variable peut être à la fois valeur d'entrée et de sortie d'une fonction,
ou s'il faut toujours éviter.

exemple : on calcule le produit de deux entiers en faisant :
mpz_mul(c, a, b) /* c = a*b */
Est-ce dangereux de faire
mpz_mul(a, a, b) /* a = a*b */
?

Si oui, ça devient vraiment très lourd d'écrire plus de trois calculs. Il
faut des tonnes de variables intermédiaires, on est soit obligé d'en
allouer plein, soit de les réutiliser mais du coup aucune n'a un nom
significatif.

Ce qui me fait douter, c'est que j'ai remarqué que
mpz_mod(a, a, n) /* a = a mod n */
renvoyait toujours 0.

Qu'en pensez-vous ?

Manuel.

9 réponses

Avatar
Pascal Bourguignon
mpg writes:

Bonjour,

J'écris un peu de code manipulant des grands nombres, et j'utilise pour cela
la bibliothèque GNU MP. ( http://www.gnu.org/software/gmp/manual/ )

Une chose que je n'arrive pas à deviner en lisant la doc, c'est si une
variable peut être à la fois valeur d'entrée et de sortie d'une fonction,
ou s'il faut toujours éviter.

exemple : on calcule le produit de deux entiers en faisant :
mpz_mul(c, a, b) /* c = a*b */
Est-ce dangereux de faire
mpz_mul(a, a, b) /* a = a*b */
?


Il me semble que oui, c'est dangereux.

Si oui, ça devient vraiment très lourd d'écrire plus de trois calculs. Il
faut des tonnes de variables intermédiaires, on est soit obligé d'en
allouer plein, soit de les réutiliser mais du coup aucune n'a un nom
significatif.

Ce qui me fait douter, c'est que j'ai remarqué que
mpz_mod(a, a, n) /* a = a mod n */
renvoyait toujours 0.

Qu'en pensez-vous ?


Je pense que je préfère ne pas me casser la tête avec un API de si bas
niveau. Je préfère utiliser Lisp pour faire mes calculs sur des
grands nombres.

LISP> (ext:! 50)
30414093201713378043612608166064768844377641568960512000000000000

--
__Pascal Bourguignon__ http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush

Avatar
mpg
mpg writes:
Est-ce dangereux de faire
mpz_mul(a, a, b) /* a = a*b */
?


Il me semble que oui, c'est dangereux.

Ça tombe bien, j'avais arrêté de le faire.


Qu'en pensez-vous ?


Je pense que je préfère ne pas me casser la tête avec un API de si bas
niveau. Je préfère utiliser Lisp pour faire mes calculs sur des
grands nombres.

LISP> (ext:! 50)
30414093201713378043612608166064768844377641568960512000000000000

Je n'en doute pas, mais pour l'instant j'apprends le C, pour le LISP

j'attendrai encore un peu. Une chose à la fois.


Avatar
Pascal Bourguignon
mpg writes:

mpg writes:
Est-ce dangereux de faire
mpz_mul(a, a, b) /* a = a*b */
?
Il me semble que oui, c'est dangereux.


Ça tombe bien, j'avais arrêté de le faire.


Qu'en pensez-vous ?
Je pense que je préfère ne pas me casser la tête avec un API de si

bas
niveau. Je préfère utiliser Lisp pour faire mes calculs sur des
grands nombres.
LISP> (ext:! 50)
30414093201713378043612608166064768844377641568960512000000000000

Je n'en doute pas, mais pour l'instant j'apprends le C, pour le LISP

j'attendrai encore un peu. Une chose à la fois.


Ok. Dans ce cas, je mentionnerais memcpy.

Une implémentation "naïve" de memcpy est:

void pjb_memcpy(char* dst,char* src,int length){
while(0<length--){
*dst++=*src++;
}
}

Ça marche assez bien:

char a[10]="Hello";
char b[10];
pjb_memcpy(b,a,10);


Et même ceci:

char a[10]="Bonjour";
pjb_memcpy(a,a+3,5);
assert(strcmp(a,"jour")==0);

Cependant,

char a[10]="Bonjour";
pjb_memcpy(a+1,a,6);

donne un résultat surprenant:

assert(strcmp(a,"BBBBBBB")==0);


Le memcpy standard est spécifié pour éviter ce résultat surprenant on
doit l'implémenter par exemple avec:


void memcpy(char* dst,char* src,int length){
if((int)dst<(int)src){
while(0<length--){
*dst++=*src++;
}
}else{
dst+=length;src+=length;
while(0<length--){
*(--dst)=*(--src);
}
}
}

Pour revenir à mpz, la question est que une opération va écrire le
résultat dans un ordre ou un autre. Si elle écrit le résultat qui se
superpose à la donnée d'entrée dans un ordre compatible avec la
lecture, ça peut fonctionner. Mais si l'algorithme nécessite d'écrire
des mots avant qu'ils ne soient lu, cela faussera le résultat.

--
__Pascal Bourguignon__ http://www.informatimago.com/

In a World without Walls and Fences,
who needs Windows and Gates?



Avatar
Jean-Marc Bourguet
Pascal Bourguignon writes:

Le memcpy standard est spécifié pour éviter ce résultat surprenant on
doit l'implémenter par exemple avec:


Tu confonds memcpy et memmove.

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

Avatar
Pascal Bourguignon
Jean-Marc Bourguet writes:

Pascal Bourguignon writes:

Le memcpy standard est spécifié pour éviter ce résultat surprenant on
doit l'implémenter par exemple avec:


Tu confonds memcpy et memmove.


Oui en effet, c'est memmove qui permet de copier des zones se chevauchant.

--
__Pascal Bourguignon__ http://www.informatimago.com/

"Indentation! -- I will show you how to indent when I indent your skull!"


Avatar
mpg
Pascal Bourguignon wrote:

mpg writes:

mpg writes:
Est-ce dangereux de faire
mpz_mul(a, a, b) /* a = a*b */
?
Il me semble que oui, c'est dangereux.


Ça tombe bien, j'avais arrêté de le faire.





Ah, je viens de trouver dans le manuel des phrases, et des exemples, qui
suggèrent fortement qu'on a le droit de la faire. Il semblerait donc que le
problème avec le modulo soit un bug... Bref, j'ai trouvé l'adresse de la
m-l gmp, je posterai dessu, ça sera plus à sa place qu'ici.

Qu'en pensez-vous ?
Je pense que je préfère ne pas me casser la tête avec un API de si

bas
niveau. Je préfère utiliser Lisp pour faire mes calculs sur des
grands nombres.
LISP> (ext:! 50)
30414093201713378043612608166064768844377641568960512000000000000

Je n'en doute pas, mais pour l'instant j'apprends le C, pour le LISP

j'attendrai encore un peu. Une chose à la fois.


Ok. Dans ce cas, je mentionnerais memcpy.

[...]


Pour revenir à mpz, la question est que une opération va écrire le
résultat dans un ordre ou un autre. Si elle écrit le résultat qui se
superpose à la donnée d'entrée dans un ordre compatible avec la
lecture, ça peut fonctionner. Mais si l'algorithme nécessite d'écrire
des mots avant qu'ils ne soient lu, cela faussera le résultat.

Ok, merci pour cet exemple instructif. Je n'ai pas l'énergie intellectuelle

de l'étudier en détail ce soir, mais il me semble avoir saisi l'argument :
pour pouvoir appeler
sa_fonction(a, a);
où le premier a est la valeur de retour, et le deuxième l'argument, sans
souci, il faut que la personne qui a implémenté la fonction se soit
éventuellement donné la peine de rendre cet usage possible.

La question, pour mon usage, est donc de savoir dans quelle mesure les
concepteurs de GMP ont fait cet effort. Et comme je le disais plus haut, le
manuel suggère assez fortement qu'ils l'ont fait, même si j'ai eu un
problème a = a mod n.

Je vais donc l'adresser à la mailing-list spécialisée pour avoir plus de
détails là-dessus, à moins que quelqu'un ici n'ait déjà expérimenté ce
genre de question avec GMP.

Manuel.




Avatar
Venus²²
"Pascal Bourguignon" wrote in message
news:
mpg writes:

Bonjour,

J'écris un peu de code manipulant des grands nombres, et j'utilise pour
cela
la bibliothèque GNU MP. ( http://www.gnu.org/software/gmp/manual/ )

Une chose que je n'arrive pas à deviner en lisant la doc, c'est si une
variable peut être à la fois valeur d'entrée et de sortie d'une fonction,
ou s'il faut toujours éviter.

exemple : on calcule le produit de deux entiers en faisant :
mpz_mul(c, a, b) /* c = a*b */
Est-ce dangereux de faire
mpz_mul(a, a, b) /* a = a*b */
?


Il me semble que oui, c'est dangereux.



Non, c'est pas dangereux du tout, parce que le compileur utilise les
registreurs de processeur pour faire la calculation. Le resultat sera mis à
la destination dans la memoire (a) par exemple.

Vénus²²


Avatar
Vincent Lefevre
Dans l'article ,
Pascal Bourguignon écrit:

mpg writes:

exemple : on calcule le produit de deux entiers en faisant :
mpz_mul(c, a, b) /* c = a*b */
Est-ce dangereux de faire
mpz_mul(a, a, b) /* a = a*b */
?


Il me semble que oui, c'est dangereux.


Non, c'est OK: GMP détecte quand une variable est réutilisée et fait
une copie temporaire (idem pour MPFR). Enfin, vérifier dans la doc,
car il y a peut-être des exceptions.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)


Avatar
lov8
Bonjour,

je ne comprends pas la logique des tests avec while/if etc avec la librairie gmp
par exple, ceci ne marche pas chez moi :

max fixé a 13, et i à 2

while(i < max){
mpz_add(i, i, un);
if (i < max){
printf("ça doit marcher");
}else{
printf("ça ne doit pas marcher");
}
}

le test (i < max) est tjrs validé alors que i devient bien plus grand que max

y a til une erreur qq part?