/* * * Operations sur les scalaires ( rationnels ) * */ #include #include #include "scalaires.h" #include "exceptions.h" #ifdef HAVE_CONFIG_H #include "config.h" #else #define _(x) x #endif /* Cette précision est utilisée dans le cas où nous devons convertir un double en rationnel */ #define PRECISION 1E6 typedisplay display; /* Fonction interne uniquement */ static unsigned long long pgcd(unsigned long long a, unsigned long long b) { if (a < b) return pgcd(b, a); if (!b) return a; return pgcd(b, a % b); } rationnel rat_constr_zero(void) { /* renvoie 0 */ rationnel temp; temp.num = 0; temp.denom = 1; return temp; } rationnel rat_constr(unsigned long long num, unsigned long long denom) { /* cree une fraction */ rationnel temp; int sgnnum = 1, sgndenom = 1; if (num < 0) { sgnnum = -1; num = -num; } if (denom < 0) { sgndenom = -1; denom = -denom; } if (!num) { temp.num = 0; temp.denom = 1; } else if (denom) { temp.num = sgnnum * sgndenom * num / pgcd(num, denom); temp.denom = denom / pgcd(num, denom); } else { exception(2, _("rat_constr: division by zero")); } return temp; } rationnel rat_constr_from_double(double flt) { /* cree une fraction a partir d un double */ return rat_constr(floor(flt * PRECISION), PRECISION); } void rat_destruct(rationnel rat) { /* destructeur */ } double rat_to_double(rationnel rat) { /* obtention du double correspondant a un rationnel */ return ((double) rat.num / (double) rat.denom); } rationnel rat_addition(rationnel rat1, rationnel rat2) { /* addition */ return rat_constr(rat1.num * rat2.denom + rat2.num * rat1.denom, rat1.denom * rat2.denom); } rationnel rat_soustraction(rationnel rat1, rationnel rat2) { /* soustraction */ return rat_constr(rat1.num * rat2.denom - rat2.num * rat1.denom, rat1.denom * rat2.denom); } rationnel rat_moinsunaire(rationnel rat1) { /* moins unaire */ return rat_constr(-rat1.num, rat1.denom); } rationnel rat_multiplication(rationnel rat1, rationnel rat2) { /* multiplication */ return rat_constr(rat1.num * rat2.num, rat1.denom * rat2.denom); } rationnel rat_division(rationnel rat1, rationnel rat2) { /* division */ if (!rat2.num) exception(2,_("division by zero")); return rat_constr(rat1.num * rat2.denom, rat1.denom * rat2.num); } /* On choisit délibérément de faire une puissance 'lente' pour éviter de faire des overflow trop facilement */ rationnel rat_pow(rationnel rat, unsigned int p) { /* puissance */ for (; p; p--) { rat = rat_multiplication(rat, rat); } return rat; } /* On convertit un rationnel en une chaîne. Le booléen first indique si on le rationnel devra être placé en début de chaîne (pour les signes) */ char *rat_to_string(rationnel rat, int first) { static char resultat[128]; char temp[64]; resultat[0] = '\0'; if (rat.num<0) { rat.num=-rat.num; if (first) { strcat(resultat,"-"); } else { strcat(resultat,"- "); } } else { if (!first) { strcat(resultat,"+ "); } } switch(display) { case DEC: if (rat.denom==1) sprintf(temp,"%qd", rat.num); else sprintf(temp,"%qd/%qd", rat.num, rat.denom); break; case HEX: if (rat.denom==1) sprintf(temp,"0x%qx", rat.num); else sprintf(temp,"0x%qx/0x%qx", rat.num, rat.denom); break; case OCT: if (rat.denom==1) sprintf(temp,"0%qo", rat.num); else sprintf(temp,"0%qo/0%qo", rat.num, rat.denom); break; case FLT: sprintf(temp,"%g", rat_to_double(rat)); break; } strcat(resultat, temp); return resultat; }