From 3b37a00a4be251f87e543d269489cb7a989425d5 Mon Sep 17 00:00:00 2001 From: Pixel Date: Sat, 28 Apr 2001 21:40:25 +0000 Subject: Hop, gros bordel, plein de fichiers ajoutes et supprimes :) --- lib/Makefile.am | 10 ++ lib/exceptions.c | 84 ++++++++++++++++ lib/hash.c | 188 +++++++++++++++++++++++++++++++++++ lib/main.c | 36 +++++++ lib/numbers.c | 100 +++++++++++++++++++ lib/parser.c | 295 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pile.c | 292 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/polynom.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/scalaires.c | 95 ++++++++++++++++++ 9 files changed, 1377 insertions(+) create mode 100644 lib/Makefile.am create mode 100644 lib/exceptions.c create mode 100644 lib/hash.c create mode 100644 lib/main.c create mode 100644 lib/numbers.c create mode 100644 lib/parser.c create mode 100644 lib/pile.c create mode 100644 lib/polynom.c create mode 100644 lib/scalaires.c (limited to 'lib') diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..e1d12c2 --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,10 @@ +localedir = $(datadir)/locale +DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@ +AM_CFLAGS = -O3 -Wall -Wstrict-prototypes $(CFLAGS) +INCLUDES = -I. -I.. -I$(includedir) -I../include +lib_LTLIBRARIES = libPolynom.la + +libPolynom_la_SOURCES = exceptions.c hash.c main.c numbers.c parser.c pile.c polynom.c scalaires.c + +libPolynom_la_LDFLAGS = -version-info $(Polynom_VERSION_INFO) + diff --git a/lib/exceptions.c b/lib/exceptions.c new file mode 100644 index 0000000..cd8bf81 --- /dev/null +++ b/lib/exceptions.c @@ -0,0 +1,84 @@ +/* + * + * Gestionnaire d'exceptions + * + */ + +#include +#include +#include +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define _(x) x +#endif +#include "exceptions.h" + +char *contexts[128]; +int clevel = 0; + +char *Estrdup(char *o) +{ + char *r; + + if (o) { + if (!(r = strdup(o))) { + exception(1, _("Out of memory.")); + } + } else { + return NULL; + } + return r; +} + +void *Emalloc(size_t s) +{ + void *r; + + if (s) { + if (!(r = malloc(s))) { + exception(1, _("Out of memory.")); + } + } else { + return NULL; + } + return r; +} + +void pushcontext(char *c) +{ + if (clevel == 128) { + exception(1, _("Too much error contexts during pushcontext().")); + } + contexts[clevel++] = Estrdup(c); +#ifdef DEBUG + fprintf(stderr,"%s\n",c); +#endif +} + +void popcontext(void) +{ + if (clevel == 0) { + exception(1, _("Error context empty, but popcontext() called.")); + } + free(contexts[--clevel]); +} + +void flushcontext(void) +{ + while (clevel) { + popcontext(); + } +} + +void exception(int level, char *msg) +{ + int i; + + fprintf(stderr, "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); + exit(level); +} diff --git a/lib/hash.c b/lib/hash.c new file mode 100644 index 0000000..9ac65bb --- /dev/null +++ b/lib/hash.c @@ -0,0 +1,188 @@ +/* + * + * Tables de hachage + * + */ + +#include +#include +#include +#include "hash.h" +#include "exceptions.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define _(x) x +#endif + + +static char *CHAINEHACHAGE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; + +static int FonctionHachage(char *clef) +{ + unsigned int i; + + if (!clef) { + exception(1, _("Internal error into hashing")); + } + + for (i = 0; i < strlen(CHAINEHACHAGE); i++) { + if (clef[0] == CHAINEHACHAGE[i]) { + return (i); + } + } + return strlen(CHAINEHACHAGE); +} + +_Element CreerElement(char *Nom, _TypeVariable Var) +{ + _Element e; + + e.NomVar = Estrdup(Nom); + + e.Variable = Var; + return (e); +} + +static _ListeChaine InserTete(_ListeChaine l, _Element e) +{ + _ListeChaine aux; + unsigned int i; + + aux = (_ListeChaine) Emalloc(sizeof(struct _LstChn)); + aux->Elem.NomVar = (char *) Emalloc(sizeof(char) * (strlen(e.NomVar) + 1)); + + for (i = 0; i <= strlen(e.NomVar); i++) { + aux->Elem.NomVar[i] = e.NomVar[i]; + } + aux->Elem.Variable = e.Variable; + aux->Suivant = l; + return (aux); +} + +static int EgaliteChaine(char *ch1, char *ch2) +{ + unsigned int i; + + if (strlen(ch1) != strlen(ch2)) { + return (0); + } + for (i = 0; i < strlen(ch1); i++) { + if (ch1[i] != ch2[i]) { + return (0); + } + } + return (1); + /* return (1-strcmp(ch1,ch2)); */ +} + +static void Supprimer(_ListeChaine * l, char *Nom) +{ + _ListeChaine l_aux = NULL; + + if ((*l) != NULL) { + if (EgaliteChaine((*l)->Elem.NomVar, Nom)) { + l_aux = *l; + *l = (*l)->Suivant; + free(l_aux->Elem.NomVar); + free(l_aux); + } else { + Supprimer(&((*l)->Suivant), Nom); + } + } +} + +static void Detruit(_ListeChaine * l) +{ + _ListeChaine l_aux = NULL; + + while (*l) { + l_aux = (*l)->Suivant; + free((*l)->Elem.NomVar); + free(*l); + *l = l_aux; + } +} + +char SupprimerDansTab(_TableauVariable * t, char *Nom) +{ + int index = FonctionHachage(Nom); + + if (0 <= index && index <= strlen(CHAINEHACHAGE)) { + Supprimer(&((*t)[index]), Nom); + } else { + return (0); + } + return (1); +} + +char InsererVarDansTab(_TableauVariable * t, _Element e) +{ + int index = FonctionHachage(e.NomVar); + + if (0 <= index && index <= strlen(CHAINEHACHAGE)) { + (*t)[index] = InserTete((*t)[index], e); + } else { + return (0); + } + return (1); +} + +static _TypeVariable NomVarToVarListe(char *Nom, _ListeChaine l, char *trouve) +{ + *trouve = 0; + while (l != NULL) { + if (EgaliteChaine(Nom, (l->Elem).NomVar)) { + *trouve = 1; + return (l->Elem.Variable); + } + l = l->Suivant; + } + return (NULL); +} + +_TypeVariable NomVarToVar(char *Nom, _TableauVariable t, char *trouve) +{ + return (NomVarToVarListe(Nom, t[FonctionHachage(Nom)], trouve)); +} + +void AfficheListe(_ListeChaine l) +{ + while (l != NULL) { + fprintf(stderr, "%s\n", l->Elem.NomVar); + l = l->Suivant; + } +} + +void AfficheTableau(_TableauVariable t) +{ + unsigned int i; + + for (i = 0; i < TAILLECHAINEHACHAGE; i++) { + AfficheListe(t[i]); + } +} + +int Initialise(_TableauVariable * t) +{ + unsigned int i; + + + (*t) = (_TableauVariable) Emalloc(sizeof(_ListeChaine) * (strlen(CHAINEHACHAGE) + 1)); + for (i = 0; i <= strlen(CHAINEHACHAGE); i++) { + (*t)[i] = NULL; + } + return (i); +} + +void DetruitTab(_TableauVariable * t) +{ + int i; + + for (i = 0; i <= strlen(CHAINEHACHAGE); i++) { + Detruit(&((*t)[i])); + } + + free(*t); + *t = NULL; +} diff --git a/lib/main.c b/lib/main.c new file mode 100644 index 0000000..19f2fb6 --- /dev/null +++ b/lib/main.c @@ -0,0 +1,36 @@ +/* + * + * Programme principal + * + */ + +#include +#include "main.h" +#include "hash.h" +#include "parser.h" +#include "polynom.h" +#include "pile.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define _(x) x +#endif + +_TableauVariable variables; +char mute; + +int main(void) +{ + + Initialise(&variables); + mute = 'x'; /* nom de la variable utilisee pour la saisie des polynomes, a recuperer en argv eventuellt */ + parse_line("x^2+x+1;"); + //parse_line("P(2);"); + //printf("%s\n", affichage_level_1()); + return 0; + + +/* destruction de ts les polynomes stockes dans la table de hh */ +/* appel a la fonction de vidage de pile */ +/* vraiment utile? on quitte le prog, ttes les donnes dynamiques seront detruites ... */ +} diff --git a/lib/numbers.c b/lib/numbers.c new file mode 100644 index 0000000..831639b --- /dev/null +++ b/lib/numbers.c @@ -0,0 +1,100 @@ +/* + * + * Conversion de chaines en nombres ( entier ou flottant ) + * + */ + + +#include "numbers.h" + + +/* Cette fonction lit un nombre. Elle va chercher absolument à traduire la chaîne passée en argument en un nombre. Si +ce nombre n'est pas valide, alors l'int valid est mis à faux. Cette fonction reconnais les nombres en décimaux, les nombres +en octal préfixés avec 0 et les nombres en hexadécimal préfixés avec 0x. +*/ + +int char_to_number(char *st, int *valid) +{ + int whattype = 0, result = 0; + + *valid = 0; + + if (*st == '0') { + st++; + if (*st == 'x') { + whattype = 1; + st++; + } else if (*st) { + whattype = 2; + } else { + *valid = 1; + return 0; + } + } + + while (*st) { + switch (whattype) { + case 0: + if ((*st < '0') || (*st > '9')) { + return 0; + } + result *= 10; + result += *st - '0'; + break; + case 1: + if (((*st < '0') || (*st > '9')) + && ((*st < 'A') || (*st > 'F')) + && ((*st < 'a') || (*st > 'f'))) { + return 0; + } + result *= 16; + if ((*st >= '0') && (*st <= '9')) { + result += *st - '0'; + } else if ((*st >= 'A') && (*st <= 'F')) { + result += *st - 'A' + 10; + } else { + result += *st - 'a' + 10; + } + break; + case 2: + if ((*st < '0') || (*st > '7')) { + return 0; + } + result *= 8; + result += *st - '0'; + break; + } + st++; + } + + *valid = 1; + return result; +} + + +/* TODO: Rajouter la precision dans les valeurs retournees */ +double char_to_double(char *st, int *valid) /* cette fonction tente de traduire une chaine en flottant */ +{ + unsigned int dotnum = 0; + unsigned int deci = 1; + double result = 0; + + while (*st) { + if (*st == '.') { + dotnum++; + } else { + if ((*st < '0') || (*st > '9') || (dotnum > 1)) { + *valid = 0; + return 0; + } else { + result *= 10; + result += *st - '0'; + if (dotnum == 1) + deci *= 10; + } + } + } + result = result / deci; + *valid = 1; + return result; +} diff --git a/lib/parser.c b/lib/parser.c new file mode 100644 index 0000000..3f0c6ce --- /dev/null +++ b/lib/parser.c @@ -0,0 +1,295 @@ +/* + * + * Interpreteur de ligne de commande + * + */ +#include +#include +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define _(x) x +#endif +#include "exceptions.h" +#include "parser.h" +#include "pile.h" + + +typedef unsigned char op_t; + +typedef struct operator_t { + op_t op; + int pri, func; +} operator_t; + +static op_t pile_operators[PILEOP_MAX]; +static int pile_nestedcall[PILECALL_MAX]; + +static int pileop_pos = 0, pilecall_pos = 0; + +/* La liste des opérateurs reconnus par le parser */ + +static operator_t operators[] = { + {',', 0, OP_NEST}, + {'+', 2, OP_PLUS}, + {'-', 2, OP_MOINS}, + {'*', 3, OP_MUL}, + {'/', 3, OP_DIV}, + {'%', 3, OP_MOD}, + {'^', 4, OP_EXP}, + {'+' + 128, 5, OP_PLUS_UNARY}, + {'-' + 128, 5, OP_MOINS_UNARY}, + {'=', 1, OP_ASSIGN}, + {'(', 6, OP_FUNC_CALL}, + {'(' + 128, 6, OP_LPAREN}, + {255, -1, -1} +}; + + + + +/* Fonction interne: convertit un operateur en sa structure */ + +static operator_t get_op(op_t op) +{ + int i; + + for (i = 0; operators[i].op != 255; i++) { + if (operators[i].op == op) + return operators[i]; + } + + return operators[i]; +} + +/* Fonctions internes de lectures sur la structure */ + +static int get_pri(op_t op) +{ + return get_op(op).pri; +} + +static int get_func(op_t op) +{ + return get_op(op).func; +} + +/* Focntions internes d'empilement / dépilement */ + +static op_t get_last_op(void) +{ + if (pileop_pos) + return pile_operators[pileop_pos - 1]; + else + return -1; +} + +static op_t pop_op(void) +{ + if (pileop_pos) + return pile_operators[--pileop_pos]; + return -1; +} + +static void push_op(op_t op) +{ + if (pileop_pos != PILEOP_MAX) + pile_operators[pileop_pos++] = op; + else + exception(-1, _("Too many nested operators in expression.\n")); + +} + +static int pop_call(void) +{ + if (pilecall_pos) + return pile_nestedcall[--pilecall_pos]; + return -1; +} + +static void increment_call(void) +{ + if (pilecall_pos) { + if (pile_nestedcall[pilecall_pos - 1] != -1) + pile_nestedcall[pilecall_pos - 1]++; + } +} + +static int get_last_call(void) +{ + if (pilecall_pos) + return pile_nestedcall[pilecall_pos - 1]; + return -1; +} + +static void push_call(int call) +{ + if (pilecall_pos != PILECALL_MAX) + pile_nestedcall[pilecall_pos++] = call; + else + exception(-1, _("Too many nested functions calls in expression.\n")); +} + +/* Cette fonction lit un "mot" sur la chaine line et renvoit le nouveau pointeur */ + +static char *getword(char *line, char *p) +{ + char o = 0, *d = line, instring = 0, gotbslash = 0; + + do { + if (instring) { + o = *(p++) = *line; + if (!gotbslash) { + switch (instring) { + case 1: + if (*line == '\'') { + instring = 0; + } + break; + case 2: + if (*line == '"') { + instring = 0; + } + break; + } + if (*line == '\\') + gotbslash = 1; + } else { + gotbslash = 0; + } + } else { + if (*(line) == '\'') { + o = *(p++) = *line; + instring = 1; + } else if (*(line) == '"') { + o = *(p++) = *line; + instring = 2; + } else { + if (*(line) != ' ' && *(line) != '\t') { + o = *(p++) = *line; + } else if (d != line) { + *p = '\0'; + return line; + } + } + } + line++; + } + while (((*line) && (*line != ')') && (*line != ']') + && (*line != ';') && (get_func(*line) == -1) + && (get_func(o) == -1)) || (instring)); + *p = '\0'; + return line; +} + +/* Cette fonction va parcourir une chaine afin d'appeler les fonction push_pile() et act_pile() */ + +void parse_line(char *line) +{ + char buffer[BUFSIZ], imm[BUFSIZ], *d = line; + op_t op; + int got_unary = 128, nbrargs; + + sprintf(buffer, "Read line '%s'", line); + pushcontext(buffer); + + while (*line) { + line = getword(line, buffer); + sprintf(imm, "Analysing word '%s' at position %i", buffer, line - d); + pushcontext(imm); + if (get_func(buffer[0]) != -1) { + /* Le mot lut est un operateur, on agit sur la pile */ + buffer[0] += got_unary; + if (got_unary) { + } + if (get_pri(buffer[0]) == -1) { + if (got_unary) { + exception(-1, _("Invalid unary operator")); + } else { + exception(-1, _("Invalid binary operator")); + } + } + while (get_pri(get_last_op()) >= get_pri(buffer[0]) + && (((get_last_op() & 127) != '(') + && ((get_last_op() & 127) != '['))) { + act_pile(get_func(pop_op())); + got_unary = 0; + } + if (buffer[0] == '(') { + push_call(0); + } + if (buffer[0] == ',') { + increment_call(); + } else + push_op(buffer[0]); + got_unary = 128; + } else if ((buffer[0] == ';') || (buffer[0] == ')') + || (buffer[0] == ']')) { + /* Le mot lut est un opérateur spécial, on vide la pile */ + switch (buffer[0]) { + case ';': + /* Equivalent a fin de ligne */ + while (pileop_pos) { + op = pop_op(); + if (op == '(') + exception(-1, _("Parse error: too much left parenthesis")); + act_pile(get_func(op)); + } + popcontext(); + popcontext(); + return; + case ')': + /* Fin de parenthese (Appel de fonction ou expression mathématique) */ + while (1) { + if (!pileop_pos) + exception(-1, _("Parse error: too much right parenthesis")); + op = pop_op(); + if (((op & 127) == '(')) + break; + if (((op & 127) == '[')) + exception(-1, _("Parse error: enclosure mismatch")); + act_pile(get_func(op)); + } + if (op == '(') { + nbrargs = pop_call(); + push_pile_int(nbrargs); + act_pile(get_func(op)); + } + got_unary = 0; + break; + case ']': + /* Fin d'opérateur de décalage */ + while (1) { + if (!pileop_pos) + exception(-1, _("Parse error: too much right parenthesis")); + op = pop_op(); + if (((op & 127) == '[')) + break; + if (((op & 127) == '(')) + exception(-1, _("Parse error: enclosure mismatch")); + act_pile(get_func(op)); + } + act_pile(get_func(op)); + got_unary = 0; + break; + } + } else if (((buffer[0] >= 'A') && (buffer[0] <= 'Z')) + || ((buffer[0] >= 'a') && (buffer[0] <= 'z')) + || ((buffer[0] >= '0') && (buffer[0] <= '9')) + || (buffer[0] == '_') || (buffer[0] == '"') + || (buffer[0] == '\'') || (buffer[0] == '.') + || (buffer[0] == '#') || (buffer[0] == '?')) { + /* Dans tous les autres cas, on a reçu un symbole, on le pose sur la pile */ + push_pile(buffer); + got_unary = 0; + if (!get_last_call()) + increment_call(); + } else if (buffer[0]) { + exception(-1, _("Invalid character")); + } + popcontext(); + } + + popcontext(); +} + diff --git a/lib/pile.c b/lib/pile.c new file mode 100644 index 0000000..a1cac21 --- /dev/null +++ b/lib/pile.c @@ -0,0 +1,292 @@ +/* + * + * Gestion de la pile des operandes + * + */ +#include +#include "pile.h" +#include "exceptions.h" +#include "numbers.h" +#include "main.h" +#include "parser.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define _(x) x +#endif + +/* FIXME manque procedure vidage de pile en fin de prog */ + +pile_elem pile[PILE_MAX]; +unsigned int pile_ptr = 0; + +void push_pile(char *st) +{ + int valid1, valid2, valid3; + char valid4=0; + int i_number; + double d_number; + polynome poly; + + + i_number = char_to_number(st, &valid1); + d_number = char_to_double(st, &valid2); + valid3 = is_mute(st); + poly = (polynome) NomVarToVar(st, variables, &valid4); + + if (valid1) { /* il s agit d un entier */ + push_pile_poly(ply_constr(rat_constr(i_number, 1), 0)); + } else if (valid2) { /* il s agit d un flottant */ + push_pile_poly(ply_constr(rat_constr_from_double(d_number), 0)); + } else if (valid3) { /* il s agit de x */ + push_pile_poly(ply_constr(rat_constr(1, 1), 0)); + } else if (valid4) { /* il s agit d une variable */ + push_pile_poly(ply_copy(poly)); + } else { /* il s agit d un nom */ + push_pile_string(Estrdup(st)); + } +} + + +void push_pile_poly(polynome poly) +{ + if (pile_ptr != PILE_MAX) { + pile[pile_ptr].type = T_POLY; + pile[pile_ptr].poly = poly; + pile_ptr++; + } else { + exception(1, _("push_pile_poly: Stack Overflow")); + } + +} + +void push_pile_int(int val) +{ + if (pile_ptr != PILE_MAX) { + pile[pile_ptr].type = T_INT; + pile[pile_ptr].val = val; + pile_ptr++; + } else { + exception(1, _("push_pile_int: Stack Overflow")); + } + +} + +void push_pile_string(char *st) +{ + if (pile_ptr != PILE_MAX) { + pile[pile_ptr].type = T_STRING; + pile[pile_ptr].label = Estrdup(st); + pile_ptr++; + } else { + exception(1, _("push_pile_string: Stack Overflow")); + } + +} + +pile_elem pop_pile(unsigned int count) +{ + char buf[50]; + + if ((int) (pile_ptr - count) >= 0) { + pile_ptr -= count; + } else { + sprintf(buf, _("pop_pile: Can't pop %u elements"), count); + exception(1, buf); + } + return pile[pile_ptr]; +} + +char *affichage_level_1(void) +{ + char *result=NULL; + + if (!pile_ptr) { + switch (pile[pile_ptr - 1].type) { + case T_POLY: + result = ply_affichage(pile[pile_ptr - 1].poly); + break; + case T_STRING: + result = pile[pile_ptr - 1].label; + break; + case T_INT: + result = (char *) Emalloc(11 * sizeof(char)); + sprintf(result, "%10d", pile[pile_ptr - 1].val); + break; + } + } + return result; +} + +int is_mute(char *st) +{ /* FIXME: test lowercase / uppercase */ + char buf[2]; + + sprintf(buf, "%c", mute); + return strcmp(st, buf); +} + + +void act_pile(int func) +{ + pile_elem operande1, operande2; + char buf[50]; + + sprintf(buf, _("Calling act_pile(%i)\n"), func); + pushcontext(buf); + switch (func) { + case OP_PLUS: + operande1 = pop_pile(1); + operande2 = pop_pile(1); + if ((operande1.type == T_POLY) && (operande2.type == T_POLY)) { + push_pile_poly(ply_addition(operande1.poly, operande2.poly)); + if (operande1.poly) + ply_destruct(operande1.poly); + if (operande2.poly) + ply_destruct(operande2.poly); + } else { + exception(1, _("act_pile: OP_PLUS invalid arguments")); + } + break; + case OP_MOINS: + operande1 = pop_pile(1); + operande2 = pop_pile(1); + if ((operande1.type == T_POLY) && (operande2.type == T_POLY)) { + push_pile_poly(ply_soustraction(operande1.poly, operande2.poly)); + if (operande1.poly) + ply_destruct(operande1.poly); + if (operande2.poly) + ply_destruct(operande2.poly); + } else { + exception(1, _("act_pile: OP_MOINS invalid arguments")); + } + break; + case OP_MUL: + operande1 = pop_pile(1); + operande2 = pop_pile(1); + if ((operande1.type == T_POLY) && (operande2.type == T_POLY)) { + push_pile_poly(ply_multiplication(operande1.poly, operande2.poly)); + if (operande1.poly) + ply_destruct(operande1.poly); + if (operande2.poly) + ply_destruct(operande2.poly); + } else { + exception(1, _("act_pile: OP_MUL invalid arguments")); + } + break; + case OP_DIV: + operande1 = pop_pile(1); + operande2 = pop_pile(1); + if ((operande1.type == T_POLY) && (operande2.type == T_POLY)) { + push_pile_poly(ply_division(operande1.poly, operande2.poly)); + if (operande1.poly) + ply_destruct(operande1.poly); + if (operande2.poly) + ply_destruct(operande2.poly); + } else { + exception(1, _("act_pile: OP_DIV invalid arguments")); + } + break; + case OP_MOD: + operande1 = pop_pile(1); + operande2 = pop_pile(1); + if ((operande1.type == T_POLY) && (operande2.type == T_POLY)) { + push_pile_poly(ply_modulo(operande1.poly, operande2.poly)); + if (operande1.poly) + ply_destruct(operande1.poly); + if (operande2.poly) + ply_destruct(operande2.poly); + } else { + exception(1, _("act_pile: OP_MOD invalid arguments")); + } + break; + case OP_EXP: + operande1 = pop_pile(1); + operande2 = pop_pile(1); + if ((operande1.type == T_POLY) && (operande2.type == T_POLY)) { + if (operande2.poly) { + if ((operande2.poly->coef.denom == 1) + && (operande2.poly->coef.num >= 0)) { + push_pile_poly(ply_exposant + (operande1.poly, operande2.poly->coef.num)); + if (operande1.poly) + ply_destruct(operande1.poly); + ply_destruct(operande2.poly); + } else { + exception(1, _("act_pile: OP_EXP invalid arguments")); + } + } else { + exception(1, _("act_pile: OP_EXP invalid arguments")); + } + } else { + exception(1, _("act_pile: OP_EXP invalid arguments")); + } + break; + case OP_ASSIGN: /* FIXME: sens de l evaluation ? poly label sto ou label poly sto */ + operande1 = pop_pile(1); + operande2 = pop_pile(1); + if ((operande1.type == T_POLY) && (operande2.type == T_STRING)) { + if (operande2.label) { + InsererVarDansTab(&variables, + CreerElement(operande2.label, + (void *) operande1.poly)); + if (operande1.poly) + ply_destruct(operande1.poly); + free(operande2.label); + } else { + exception(1, _("act_pile: OP_ASSIGN empty string")); + } + } else { + exception(1, _("act_pile: OP_ASSIGN invalid arguments")); + } + break; + case OP_PLUS_UNARY: + break; + case OP_MOINS_UNARY: + operande1 = pop_pile(1); + if (operande1.type == T_POLY) { + push_pile_poly(ply_soustraction + (ply_constr(rat_constr_zero(), 0), operande1.poly)); + if (operande1.poly) + ply_destruct(operande1.poly); + } else { + exception(1, _("act_pile: OP_MOINS_UNARY invalid argument")); + } + break; + case OP_FUNC_CALL: + operande1 = pop_pile(1); + if ((operande1.type == T_INT) && (operande1.val == 1)) { + operande1 = pop_pile(1); + operande2 = pop_pile(1); + if ((operande1.type == T_POLY) && (operande2.type == T_POLY)) { + if (operande2.poly) { + if (operande2.poly->degre == 0) { + push_pile_poly(ply_constr + (rat_constr_from_double + (ply_valuation + (operande1.poly, + rat_to_double(operande2.poly-> + coef))), 1)); + if (operande1.poly) + ply_destruct(operande1.poly); + ply_destruct(operande2.poly); + } else { + exception(1, + _ + ("act_pile: OP_FUNC_CALL invalid arguments")); + } + } else { + exception(1, _("act_pile: OP_FUNC_CALL invalid arguments")); + } + } else { + exception(1, _("act_pile: OP_FUNC_CALL invalid arguments")); + } + } else { + exception(1, _("act_pile: OP_FUNC_CALL incorrect argument number")); + } + break; + default: + exception(1, _("act_pile: Unknown operator")); + } + popcontext(); +} diff --git a/lib/polynom.c b/lib/polynom.c new file mode 100644 index 0000000..f1c19a2 --- /dev/null +++ b/lib/polynom.c @@ -0,0 +1,277 @@ +/* + * + * Operations sur les polynomes + * + */ + +#include "polynom.h" +#include "scalaires.h" +#include "exceptions.h" +#include "main.h" +#include +#include +#include +#include +#ifdef HAVE_CONFIG_H +#include "config.h" +#else +#define _(x) x +#endif + +/* FIXME: manque div et mod et poly_to_string */ + +polynome ply_constr(rationnel coef, int degre) +{ /* constructeur monome */ + polynome temp; + + if (!coef.num) + return NULL; + + temp = (monome *) Emalloc(sizeof(monome)); + + temp->coef = coef; + temp->degre = degre; + temp->suiv = NULL; + + return temp; +} + +polynome ply_vide(void) +{ /* cree un polynome */ + + return NULL; +} + +void ply_destruct(polynome poly) +{ /* destructeur */ + if (poly) { + ply_destruct(poly->suiv); + free(poly); + } +} + + +polynome ply_copy(polynome poly) +{ /* recopie */ + polynome result = NULL, temp = NULL, t; + + while (poly) { + t = ply_constr(poly->coef, poly->degre); + if (result) { + temp->suiv = t; + temp = t; + } else { + result = t; + temp = t; + } + poly = poly->suiv; + } + return result; +} + + + + +polynome ply_addition(polynome poly1, polynome poly2) +{ /* addition de deux polynomes */ + polynome resultat = NULL, temp = NULL, t; + rationnel newrat; + int degre; + + while (poly1 && poly2) { + if (poly1->degre > poly2->degre) { + t = ply_constr(poly1->coef, poly1->degre); + poly1 = poly1->suiv; + } else if (poly1->degre < poly2->degre) { + t = ply_constr(poly2->coef, poly2->degre); + poly2 = poly2->suiv; + } else { + newrat = rat_addition(poly1->coef, poly2->coef); + degre = poly1->degre; + t = ply_constr(newrat, degre); + poly1 = poly1->suiv; + poly2 = poly2->suiv; + } + if (t) { + if (resultat) { + temp->suiv = t; + temp = t; + } else { + resultat = t; + temp = t; + } + } + } + + while (poly1) { + t = ply_constr(poly1->coef, poly1->degre); + if (resultat) { + temp->suiv = t; + temp = t; + } else { + resultat = t; + temp = t; + } + poly1 = poly1->suiv; + } + + while (poly2) { + t = ply_constr(poly2->coef, poly2->degre); + if (resultat) { + temp->suiv = t; + temp = t; + } else { + resultat = t; + temp = t; + } + poly2 = poly2->suiv; + } + + return resultat; +} + +polynome ply_soustraction(polynome poly1, polynome poly2) +{ /* soustraction de deux polynomes */ + + polynome resultat = NULL, temp = NULL, t; + rationnel newrat; + int degre; + + while (poly1 && poly2) { + if (poly1->degre > poly2->degre) { + t = ply_constr(poly1->coef, poly1->degre); + poly1 = poly1->suiv; + } else if (poly1->degre < poly2->degre) { + t = ply_constr(rat_moinsunaire(poly2->coef), poly2->degre); + poly2 = poly2->suiv; + } else { + newrat = rat_soustraction(poly1->coef, poly2->coef); + degre = poly1->degre; + t = ply_constr(newrat, degre); + poly1 = poly1->suiv; + poly2 = poly2->suiv; + } + if (t) { + if (resultat) { + temp->suiv = t; + temp = t; + } else { + resultat = t; + temp = t; + } + } + } + + while (poly1) { + t = ply_constr(poly1->coef, poly1->degre); + if (resultat) { + temp->suiv = t; + temp = t; + } else { + resultat = t; + temp = t; + } + poly1 = poly1->suiv; + } + + while (poly2) { + t = ply_constr(rat_moinsunaire(poly2->coef), poly2->degre); + if (resultat) { + temp->suiv = t; + temp = t; + } else { + resultat = t; + temp = t; + } + poly2 = poly2->suiv; + } + + return resultat; +} + + +polynome ply_multiplication(polynome poly1, polynome poly2) +{ /* multiplication de deux polynomes */ + polynome temp = NULL, t, resultat = NULL; + + while (poly1) { + while (poly2) { + t = + ply_constr(rat_multiplication(poly1->coef, poly2->coef), + poly1->degre + poly2->degre); + if (t) { + if (resultat) { + temp->suiv = t; + temp = t; + } else { + resultat = t; + temp = t; + } + } + poly2 = poly2->suiv; + } + poly1 = poly1->suiv; + } + + return resultat; +} + +polynome ply_division(polynome poly1, polynome poly2) +{ /* division de deux polynomes */ + polynome result=NULL; + + return result; + + +} + +polynome ply_modulo(polynome poly1, polynome poly2) +{ /* reste de la division de deux polynomes */ + polynome result=NULL; + + return result; +} + +polynome ply_exposant(polynome poly, unsigned int exp) +{ /* exponentiation d'un polynome */ + int i; + polynome result, temp; + + if (poly) { + result = ply_constr(rat_constr(1, 1), 0); + for (i = 0; i < exp; i++) { + temp = ply_multiplication(result, poly); + ply_destruct(result); + result = temp; + } + } else { + result = NULL; + } + return result; + +} + +double ply_valuation(polynome poly, double point) +{ /* valuation d'un polynome en un point */ + double result = 0; + + while (poly) { + result += rat_to_double(poly->coef) * pow(point, (double) (poly->degre)); + } + return result; +} + +char *ply_affichage(polynome poly) +{ /* routine d'affichage d'un polynome */ + char buf[BUFSIZ], temp[BUFSIZ]; /* FIXME: pas glop comme routine, malloquer tout ca ? */ + + while (poly) { + if (poly->degre != 0) { + sprintf(temp, "%+f*%c^%u", rat_to_double(poly->coef), mute, poly->degre); + } else { + sprintf(temp, "%+f", rat_to_double(poly->coef)); + } + strcat(buf, temp); /* FIXME: gerer le depassement de buf si po malloc */ + } + return Estrdup(buf); +} diff --git a/lib/scalaires.c b/lib/scalaires.c new file mode 100644 index 0000000..71a106d --- /dev/null +++ b/lib/scalaires.c @@ -0,0 +1,95 @@ +/* + * + * Operations sur les scalaires ( rationnels ) + * + */ + +#include "scalaires.h" +#include + +#define PRECISION 1E6 +static int pgcd(int a, int b) +{ + if (!a) + return b; + if (a < b) + return pgcd(b, 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(int num, int denom) +{ /* cree une fraction */ + rationnel temp; + + if (denom < 0) { + denom = -denom; + num = -num; + } + + temp.num = num / pgcd(num, denom); + temp.denom = denom / pgcd(num, denom); + 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 */ + + return rat_constr(rat1.num * rat2.denom, rat1.denom * rat2.num); +} -- cgit v1.2.3