summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/exceptions.c12
-rw-r--r--lib/fonctions.c52
-rw-r--r--lib/hash.c3
-rw-r--r--lib/interface.c33
-rw-r--r--lib/numbers.c2
-rw-r--r--lib/parser.c6
-rw-r--r--lib/pile.c42
-rw-r--r--lib/polynom.c21
-rw-r--r--lib/scalaires.c16
9 files changed, 133 insertions, 54 deletions
diff --git a/lib/exceptions.c b/lib/exceptions.c
index 89d15c4..b19df9b 100644
--- a/lib/exceptions.c
+++ b/lib/exceptions.c
@@ -20,6 +20,8 @@ char *contexts[128];
int clevel = 0;
int global_error = 0;
+/* Les fonctions strdup et malloc sont réécrites ici afin de simplifier la vie en cas d'erreur. */
+
char *Estrdup(char *o)
{
char *r;
@@ -48,6 +50,8 @@ void *Emalloc(size_t s)
return r;
}
+/* Les routines de manipulation de la pile de contexte d'erreurs */
+
void pushcontext(char *c)
{
if (clevel == 128) {
@@ -82,20 +86,20 @@ void exception(int level, char *msg)
int i;
switch (level) {
case 1:
- fprintf(stderr, "Error detected. Showing context.\n");
+ fprintf(stderr, _("Non-fatal error detected. Showing context.\n"));
for (i = 0; i < clevel; i++) {
fprintf(stderr, " (%i) - %s\n", i, contexts[i]);
}
- fprintf(stderr, " Error description: %s\n", msg);
+ fprintf(stderr, _(" Error description: %s\n"), msg);
flush_pile();
global_error = 1;
break;
default:
- fprintf(stderr, "Error detected. Showing context.\n");
+ fprintf(stderr, _("Fatal error detected. Showing context.\n"));
for (i = 0; i < clevel; i++) {
fprintf(stderr, " (%i) - %s\n", i, contexts[i]);
}
- fprintf(stderr, " Error description: %s\n", msg);
+ fprintf(stderr, _(" Error description: %s\n"), msg);
clearterm();
exit(1);
break;
diff --git a/lib/fonctions.c b/lib/fonctions.c
index eca44cb..2d25eea 100644
--- a/lib/fonctions.c
+++ b/lib/fonctions.c
@@ -19,7 +19,7 @@
#define _(x) x
#endif
-
+/* Nous allons utiliser des pointeurs sur des fonctions. Voici donc les typedefs pour notre structure... */
typedef void (*func_name)(polynome arg1, polynome arg2, polynome arg3);
typedef struct func_t {
@@ -28,6 +28,7 @@ typedef struct func_t {
int arite;
} func_t;
+/* ... et la structure elle-même */
static func_t func_table[] = {
{ deriv, "deriv", 1, },
@@ -38,9 +39,13 @@ static func_t func_table[] = {
{ setdisplay, "setdisplay", 1 },
{ reinit, "reinit", 0 },
{ exit_call, "exit", 0 },
+ { setsmartprint, "setsmartprint", 1 },
{ NULL, NULL, -1 }
};
+
+/* On cherche simplement la routine a appeler parmi la table des fonctions */
+
void appel_fonction(char *nom, int arite, polynome p1, polynome p2, polynome p3)
{
int i=0;
@@ -60,9 +65,10 @@ void appel_fonction(char *nom, int arite, polynome p1, polynome p2, polynome p3)
} else {
exception(1,_("appel_fonction: non-existent function"));
}
+}
-}
+/* Fonction de dérivation - rajoute le résultat sur la pile. */
void deriv(polynome p1, polynome p2, polynome p3)
{
@@ -71,14 +77,14 @@ void deriv(polynome p1, polynome p2, polynome p3)
while (p1) {
if (p1->degre) {
t=ply_constr(rat_constr((p1->coef.num)*(p1->degre), p1->coef.denom), (p1->degre-1));
- if (t) {
- if (resultat) {
- temp->suiv = t;
- temp = t;
- } else {
- resultat = t;
- temp = t;
- }
+ if (t) {
+ if (resultat) {
+ temp->suiv = t;
+ temp = t;
+ } else {
+ resultat = t;
+ temp = t;
+ }
}
}
p1=p1->suiv;
@@ -86,15 +92,19 @@ void deriv(polynome p1, polynome p2, polynome p3)
push_pile_poly(resultat);
}
+
+/* Fonction paresseuse */
+
void derivn(polynome p1, polynome p2, polynome p3)
{ pile_elem temp;
int i;
if (p1) {
if ((p1->degre==0) && (p1->coef.num>0) && (p1->coef.denom==1)) {
- push_pile_poly(p2);
+ push_pile_poly(NULL);
for(i=0; i<p1->coef.num; i++) {
- temp=pop_pile(1);
+ temp = pop_pile(1);
+ ply_destruct(temp.poly);
deriv(temp.poly, NULL, NULL);
}
} else {
@@ -105,6 +115,9 @@ void derivn(polynome p1, polynome p2, polynome p3)
}
}
+
+/* Intégration d'un polynome */
+
void integ(polynome p1, polynome p2, polynome p3)
{
polynome resultat = NULL, temp = NULL, t;
@@ -126,6 +139,8 @@ void integ(polynome p1, polynome p2, polynome p3)
push_pile_poly(resultat);
}
+/* Quelques fonctions explicites... */
+
void printvars(polynome p1, polynome p2, polynome p3)
{
AfficheTableau(variables);
@@ -142,6 +157,7 @@ void help(polynome p1, polynome p2, polynome p3)
". setdisplay(n); set integer display format\n"
"\tn=1: DECIMAL, n=2: HEXA\n"
"\tn=3: OCTAL, n=4: FLOAT\n"
+ ". smartprint(bool); toggle smart print of polynoms\n"
". reinit(); clear all variables\n"
". exit(); end program\n"));
}
@@ -184,3 +200,15 @@ void exit_call(polynome p1, polynome p2, polynome p3)
{
quit = 1;
}
+
+void setsmartprint(polynome p1, polynome p2, polynome p3) {
+ if (p1) {
+ if ((!p1->degre)) {
+ smartprint = p1->coef.num;
+ } else {
+ exception(1, _("setsmartprint: invalid arg"));
+ }
+ } else {
+ smartprint = 0;
+ }
+}
diff --git a/lib/hash.c b/lib/hash.c
index f1cc597..5009611 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -16,6 +16,9 @@
#define _(x) x
#endif
+/* L'ensemble de ce code source nous sert à implémenter une table de hachage qui nous sera utile
+ pour le stockage des variables du programme. C'est juste histoire d'aller un peu plus vite qu'une
+ simple liste chaînée. */
static char *CHAINEHACHAGE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
diff --git a/lib/interface.c b/lib/interface.c
index f698318..3a3c6fc 100644
--- a/lib/interface.c
+++ b/lib/interface.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "config.h"
#include "interface.h"
#include "terminal.h"
@@ -9,6 +10,11 @@
int quit;
+char * ancien = NULL;
+
+/* Ces deux fonctions nous servent à insérer ou supprimer un caractère dans une chaîne. Utile pour l'utilisation des
+touches backspace, suppr et insert */
+
void supprime(char * ch) {
for (; *ch; ch++) {
*ch = *(ch + 1);
@@ -26,6 +32,9 @@ void inserer(char * ch, char c) {
*ch = c;
}
+/* La boucle de l'interface. Même si elle a l'air longue, elle ne fait que tester les différents cas
+en fonction des touches enfoncées. */
+
void ifloop(void) {
int cread, i, insert = 0;
int gotesc = 0;
@@ -44,9 +53,6 @@ void ifloop(void) {
cread = fgetc(input);
switch (cread) {
case 49: /* Home */
- for (i = 0; i < position; i++) {
- printf("\010");
- }
position = 0;
break;
case 50: /* Insert */
@@ -72,6 +78,23 @@ void ifloop(void) {
break;
}
break;
+ case 79:
+ cread = fgetc(input);
+ switch (cread) {
+ case 82: /* F3 */
+ for (i = 0; i < position; i++) {
+ printf("\010");
+ }
+ strcpy(buffer, ancien);
+ position = strlen(buffer);
+ printf("%s", buffer);
+ break;
+ default:
+ gotesc = 0;
+ break;
+
+ }
+ break;
default:
gotesc = 0;
break;
@@ -98,6 +121,8 @@ void ifloop(void) {
case 10: /* Entrée */
printf("\n");
clearterm();
+ if (ancien) free(ancien);
+ ancien = Estrdup(buffer);
parse_line(buffer);
if (quit) break;
initterm();
@@ -124,7 +149,7 @@ void ifloop(void) {
printf("\010");
}
break;
- default:
+ default: /* Tout caractère autre, on le rajoute à la position en cours */
if (insert) {
inserer(&(buffer[position]), cread);
printf("%s", &(buffer[position]));
diff --git a/lib/numbers.c b/lib/numbers.c
index 7d0c64a..100cabd 100644
--- a/lib/numbers.c
+++ b/lib/numbers.c
@@ -73,7 +73,7 @@ int char_to_number(char *st, int *valid)
rationnel char_to_rat(char *st, int *valid)
-{ /* cette fonction tente de traduire une chaine en flottant */
+{ /* cette fonction tente de traduire une chaine en rationnel */
int dotnum = 0, deci = 1, temp = 0;
while (*st) {
diff --git a/lib/parser.c b/lib/parser.c
index 529516b..74a7b71 100644
--- a/lib/parser.c
+++ b/lib/parser.c
@@ -3,6 +3,7 @@
* Interpreteur de ligne de commande
*
*/
+
#include <stdio.h>
#include <limits.h>
#ifdef HAVE_CONFIG_H
@@ -45,9 +46,6 @@ static operator_t operators[] = {
{255, -1, -1}
};
-
-
-
/* Fonction interne: convertit un operateur en sa structure */
static operator_t get_op(op_t op)
@@ -243,8 +241,6 @@ void parse_line(char *line)
op = pop_op();
if (((op & 127) == '('))
break;
- if (((op & 127) == '['))
- exception(1, _("Parse error: enclosure mismatch"));
act_pile(get_func(op));
}
if (global_error) break;
diff --git a/lib/pile.c b/lib/pile.c
index dd43a6e..11f1327 100644
--- a/lib/pile.c
+++ b/lib/pile.c
@@ -18,8 +18,10 @@ pile_elem result_pile[PILE_MAX];
unsigned int pile_ptr = 0;
unsigned int result_pile_ptr = 0;
-/* fonctions basiques sur la pile d operandes */
+/* Fonctions basiques sur la pile d'opérandes. Elle seront appelées par le parser. */
+/* La fonction push_pile est générique. Le parser lui transmet une chaîne de caractères, et cette
+fonction va tenter de la convertir en ce qui lui semble le mieux pour empiler */
void push_pile(char *st)
{
int valid1, valid2, valid3;
@@ -35,23 +37,23 @@ void push_pile(char *st)
r_number = char_to_rat(st, &valid2);
valid3 = is_mute(st);
poly = (polynome) NomVarToVar(st, variables, &valid4);
- if (valid1) { /* il s agit d un entier */
+ if (valid1) { /* il s'agit d'un entier */
pushcontext(_("it's an integer"));
push_pile_poly(ply_constr(rat_constr(i_number, 1), 0));
popcontext();
- } else if (valid2) { /* il s agit d un flottant */
+ } else if (valid2) { /* il s'agit d'un flottant */
pushcontext(_("it's a float"));
push_pile_poly(ply_constr(r_number, 0));
popcontext();
- } else if (valid3) { /* il s agit de x */
+ } else if (valid3) { /* il s'agit de x */
pushcontext(_("it's X"));
push_pile_poly(ply_constr(rat_constr(1, 1), 1));
popcontext();
- } else if (valid4) { /* il s agit d une variable */
+ } else if (valid4) { /* il s'agit d'une variable */
pushcontext(_("it's a variable"));
push_pile_poly(ply_copy(poly));
popcontext();
- } else { /* il s agit d un nom */
+ } else { /* il s'agit d'un nom */
pushcontext(_("it's a name"));
if (*st == '\'') {
st++;
@@ -61,14 +63,12 @@ void push_pile(char *st)
popcontext();
}
popcontext();
-
-
#ifdef DEBUG
-
fprintf(stderr, "exiting push_pile\n");
#endif
}
+/* Fonctions "atomiques" appelées par push_pile() */
void push_pile_poly(polynome poly)
{
@@ -108,6 +108,8 @@ void push_pile_string(char *st)
}
+/* Dépilement */
+
pile_elem pop_pile(unsigned int count)
{
char buf[50];
@@ -121,6 +123,8 @@ pile_elem pop_pile(unsigned int count)
return pile[pile_ptr];
}
+/* Vidage (appelée en cas d'erreur) */
+
void flush_pile(void)
{
int i;
@@ -144,8 +148,8 @@ void flush_pile(void)
-/* fonctions basiques sur la pile de resultats */
-
+/* Fonctions basiques sur la pile de resultats. Grâce à cette pile résultat, nous pouvons passer un résultat
+à l'interface, dès que le parser aura terminé son travail. */
void move_to_resultat_pile(void)
{ pile_elem temp;
@@ -189,7 +193,6 @@ char * pop_resultat(void)
return result;
}
-
polynome return_last(int *valid)
{
if (!result_pile_ptr) {
@@ -202,12 +205,12 @@ polynome return_last(int *valid)
}
-
int has_resultat(void) {
return (result_pile_ptr ? 1 : 0);
}
-/* fonctions avancees sur la pile d operandes */
+/* Fonctions avancées sur la pile d'opérandes. Nous allons surtout manipuler les opérandes de la pile, à l'aide
+des opérateurs que le parser nous enverra. */
char *affichage_level_1(void)
{
@@ -223,7 +226,6 @@ char *affichage_level_1(void)
break;
case T_INT:
result = (char *) Emalloc(11 * sizeof(char));
-
sprintf(result, "%10d", pile[pile_ptr - 1].val);
break;
}
@@ -237,7 +239,7 @@ int is_mute(char *st)
return !(strcmp(st, mute));
}
-
+/* Cette fonction est appelée par le parser, et est donc un énorme switch qui va tester l'opérateur passé en paramètre */
void act_pile(int func)
{
pile_elem operande1, operande2;
@@ -423,11 +425,7 @@ void act_pile(int func)
exception(1, _("act_pile: OP_FUNC_CALL need only one argument for a polynom evaluation"));
}
if (operande[0].poly->degre == 0) {
- push_pile_poly(ply_constr
- (rat_constr_from_double
- (ply_valuation
- (operande2.poly, rat_to_double(operande[0].poly->coef))),
- 0));
+ push_pile_poly(ply_constr(ply_valuation(operande2.poly, operande[0].poly->coef), 0));
if (operande[0].poly)
ply_destruct(operande[0].poly);
ply_destruct(operande2.poly);
@@ -453,7 +451,7 @@ void act_pile(int func)
popcontext();
}
-
+/* Fonction de déboguage uniquement */
void affichage_pile(void)
{
int i;
diff --git a/lib/polynom.c b/lib/polynom.c
index b502849..e2e88d3 100644
--- a/lib/polynom.c
+++ b/lib/polynom.c
@@ -19,6 +19,7 @@
int smartprint = 1;
+/* Les fonctions de base pour la construction et la destruction de polynomes */
polynome ply_constr(rationnel coef, int degre)
{ /* constructeur monome */
polynome temp;
@@ -69,7 +70,9 @@ polynome ply_copy(polynome poly)
}
-
+/* Voici toutes les fonctions de manipulation de polynôme. La fonction d'addition est la plus importante
+puisqu'elle nous sert à construire un polynome entier à partir de monomes. Sa structure est comparable à celle
+de l'opération 'fusion' dans le cas du tri fusion */
polynome ply_addition(polynome poly1, polynome poly2)
{ /* addition de deux polynomes */
@@ -129,6 +132,7 @@ polynome ply_addition(polynome poly1, polynome poly2)
return resultat;
}
+/* Nous avons choisi de réécrire cette fonction entièrement, plutôt que de bricoler à partir de la fonction addition */
polynome ply_soustraction(polynome poly1, polynome poly2)
{ /* soustraction de deux polynomes */
@@ -188,7 +192,7 @@ polynome ply_soustraction(polynome poly1, polynome poly2)
return resultat;
}
-
+/* La fonction multiplication se base sur la fonction addition, suivant les mathématiques classiques */
polynome ply_multiplication(polynome poly1, polynome poly2)
{ /* multiplication de deux polynomes */
polynome temp = NULL, t, resultat = NULL, r, tempresult = NULL, poly2init;
@@ -220,6 +224,11 @@ polynome ply_multiplication(polynome poly1, polynome poly2)
return resultat;
}
+
+/* L'algorithme pour la division et le modulo est le même. Seul le return change. En effet, pour faire le calcul, nous
+utilisons la méthode simple vue en cours de mathématiques, qui consiste à poser la division sur une feuille et à effectuer
+une série de multiplications élémentaires et de soustractions. Nous obtenons donc le quotient ET le reste. */
+
polynome ply_division(polynome dividende, polynome diviseur)
{ /* division de deux polynomes */
polynome interdividende = ply_copy(dividende), interdiviseur = NULL, inter = NULL, reste = dividende, resultat = NULL, r = NULL;
@@ -323,12 +332,12 @@ polynome ply_exposant(polynome poly, unsigned int exp)
}
-double ply_valuation(polynome poly, double point)
-{ /* valuation d'un polynome en un point */
- double result = 0;
+rationnel ply_valuation(polynome poly, rationnel point)
+{ /* évaluation d'un polynome en un point */
+ rationnel result = rat_constr_zero();
while (poly) {
- result += rat_to_double(poly->coef) * pow(point, (poly->degre));
+ result = rat_addition(result, rat_multiplication(poly->coef, rat_pow(point, poly->degre)));
poly = poly->suiv;
}
return result;
diff --git a/lib/scalaires.c b/lib/scalaires.c
index 5dd6bb1..eb7b7c6 100644
--- a/lib/scalaires.c
+++ b/lib/scalaires.c
@@ -13,9 +13,12 @@
#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)
@@ -113,6 +116,19 @@ rationnel rat_division(rationnel rat1, rationnel rat2)
}
+/* 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)
{