File:  [local] / rpl / src / simplification.c
Revision 1.51: download - view: text, annotated - select for diffs - revision graph
Mon Oct 20 19:01:35 2014 UTC (9 years, 6 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Refonte des routines de simplification des expressions algébriques.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.19
    4:   Copyright (C) 1989-2014 Dr. BERTRAND Joël
    5: 
    6:   This file is part of RPL/2.
    7: 
    8:   RPL/2 is free software; you can redistribute it and/or modify it
    9:   under the terms of the CeCILL V2 License as published by the french
   10:   CEA, CNRS and INRIA.
   11:  
   12:   RPL/2 is distributed in the hope that it will be useful, but WITHOUT
   13:   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14:   FITNESS FOR A PARTICULAR PURPOSE.  See the CeCILL V2 License
   15:   for more details.
   16:  
   17:   You should have received a copy of the CeCILL License
   18:   along with RPL/2. If not, write to info@cecill.info.
   19: ================================================================================
   20: */
   21: 
   22: 
   23: #include "rpl-conv.h"
   24: 
   25: 
   26: /*
   27: ================================================================================
   28:   Fonction de transcription d'un arbre en liste chaînée
   29: ================================================================================
   30:   Entrées : pointeur sur une structure struct_processus
   31: --------------------------------------------------------------------------------
   32:   Sorties :
   33: --------------------------------------------------------------------------------
   34:   Effets de bord : néant
   35: ================================================================================
   36: */
   37: 
   38: static struct_liste_chainee *
   39: transcription_arbre(struct_processus *s_etat_processus, struct_arbre *s_arbre)
   40: {
   41:     integer8                i;
   42: 
   43:     struct_liste_chainee    *l_element_courant;
   44:     struct_liste_chainee    *l_liste;
   45:     struct_liste_chainee    *l_nouvelle_pile_locale;
   46:     struct_liste_chainee    *l_pile_locale;
   47: 
   48:     l_pile_locale = NULL;
   49: 
   50:     for(i = 0; i < (*s_arbre).nombre_branches; i++)
   51:     {
   52:         if ((l_nouvelle_pile_locale = allocation_maillon(s_etat_processus))
   53:                 == NULL)
   54:         {
   55:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
   56:             return(NULL);
   57:         }
   58: 
   59:         (*l_nouvelle_pile_locale).suivant = l_pile_locale;
   60:         l_pile_locale = l_nouvelle_pile_locale;
   61: 
   62:         if (((*l_pile_locale).donnee = (void *) transcription_arbre(
   63:                 s_etat_processus, (*s_arbre).branches[i])) == NULL)
   64:         {
   65:             return(NULL);
   66:         }
   67:     }
   68: 
   69:     if ((l_liste = allocation_maillon(s_etat_processus)) == NULL)
   70:     {
   71:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
   72:         return(NULL);
   73:     }
   74: 
   75:     // Ajout de la fonction
   76: 
   77:     (*l_liste).suivant = NULL;
   78:     (*l_liste).donnee = (*s_arbre).feuille;
   79: 
   80:     free((*s_arbre).branches);
   81:     free(s_arbre);
   82: 
   83:     // Chaînage des arguments
   84: 
   85:     while(l_pile_locale != NULL)
   86:     {
   87:         l_element_courant = (void *) (*l_pile_locale).donnee;
   88: 
   89:         if (l_element_courant == NULL)
   90:         {
   91:             (*s_etat_processus).erreur_systeme = d_es_pile_vide;
   92:             return(NULL);
   93:         }
   94: 
   95:         while((*l_element_courant).suivant != NULL)
   96:         {
   97:             l_element_courant = (*l_element_courant).suivant;
   98:         }
   99: 
  100:         (*l_element_courant).suivant = l_liste;
  101:         l_liste = (void *) (*l_pile_locale).donnee;
  102: 
  103:         l_nouvelle_pile_locale = (*l_pile_locale).suivant;
  104:         liberation_maillon(s_etat_processus, l_pile_locale);
  105:         l_pile_locale = l_nouvelle_pile_locale;
  106:     }
  107: 
  108:     return(l_liste);
  109: }
  110: 
  111: 
  112: /*
  113: ================================================================================
  114:   Fonction de simplification d'un arbre
  115: ================================================================================
  116:   Entrées : pointeur sur une structure struct_processus
  117: --------------------------------------------------------------------------------
  118:   Sorties :
  119: --------------------------------------------------------------------------------
  120:   Effets de bord : néant
  121: ================================================================================
  122: */
  123: 
  124: static void
  125: inversion_fonctions_arbre(struct_arbre *s_arbre)
  126: {
  127:     return;
  128: }
  129: 
  130: 
  131: static void
  132: simplification_arbre(struct_processus *s_etat_processus,
  133:         struct_arbre **s_arbre)
  134: {
  135:     return;
  136: }
  137: 
  138: 
  139: /*
  140: ================================================================================
  141:   Fonction 'simplification' (ne libère pas les paramètres)
  142: ================================================================================
  143:   Entrées : pointeur sur une structure struct_processus
  144: --------------------------------------------------------------------------------
  145:   Sorties :
  146: --------------------------------------------------------------------------------
  147:   Effets de bord : néant
  148: ================================================================================
  149: */
  150: 
  151: struct_objet *
  152: simplification(struct_processus *s_etat_processus, struct_objet *s_objet)
  153: {
  154:     struct_objet                *s_objet_simplifie;
  155: 
  156:     integer8                    i;
  157:     integer8                    nombre_arguments;
  158: 
  159:     struct_arbre                *s_arbre;
  160: 
  161:     struct_liste_chainee        *l_element_courant;
  162: 
  163:     // Attention : l_liste_locale et l_ancienne_liste_locale ne contiennent pas
  164:     // un pointeur sur une struct_objet, mais sur une struct_arbre.
  165: 
  166:     struct_liste_chainee        *l_liste_locale;
  167:     struct_liste_chainee        *l_ancienne_liste_locale;
  168: 
  169:     if ((*s_objet).type == ALG)
  170:     {
  171:         /*
  172:          * Transcription de l'expression algébrique en arbre q-aire
  173:          */
  174: 
  175:         l_liste_locale = NULL;
  176:         l_element_courant = (*s_objet).objet;
  177: 
  178:         while(l_element_courant != NULL)
  179:         {
  180:             switch((*(*l_element_courant).donnee).type)
  181:             {
  182:                 // Toutes les fonctions (intrinsèques, extrinsèques et
  183:                 // utilisateurs).
  184: 
  185:                 case FCT:
  186:                 {
  187:                     // Il s'agit d'un objet de type ALG. Nous pouvons donc
  188:                     // sauter les délimiteurs d'expression.
  189: 
  190:                     if ((l_element_courant != (*s_objet).objet) &&
  191:                             ((*l_element_courant).suivant != NULL))
  192:                     {
  193:                         nombre_arguments = (*((struct_fonction *)
  194:                                 (*(*l_element_courant).donnee).objet))
  195:                                 .nombre_arguments;
  196: 
  197:                         // Si le nombre d'arguments vaut 0, la fonction
  198:                         // apparaît en notation algébrique comme une fonction
  199:                         // infixe.
  200: 
  201:                         if (nombre_arguments == 0)
  202:                         {
  203:                             nombre_arguments = 2;
  204:                         }
  205: 
  206:                         if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
  207:                         {
  208:                             (*s_etat_processus).erreur_systeme =
  209:                                     d_es_allocation_memoire;
  210:                             return(NULL);
  211:                         }
  212: 
  213:                         (*s_arbre).inversion = d_faux;
  214:                         (*s_arbre).nombre_branches = nombre_arguments;
  215:                         (*s_arbre).feuille = copie_objet(s_etat_processus,
  216:                                 (*l_element_courant).donnee, 'P');
  217: 
  218:                         if (((*s_arbre).branches = malloc(((size_t) (*s_arbre)
  219:                                 .nombre_branches) * sizeof(struct_arbre *)))
  220:                                 == NULL)
  221:                         {
  222:                             (*s_etat_processus).erreur_systeme =
  223:                                     d_es_allocation_memoire;
  224:                             return(NULL);
  225:                         }
  226: 
  227:                         for(i = nombre_arguments - 1; i >= 0; i--)
  228:                         {
  229:                             if (l_liste_locale == NULL)
  230:                             {
  231:                                 (*s_etat_processus).erreur_execution =
  232:                                         d_ex_manque_argument;
  233:                                 return(NULL);
  234:                             }
  235: 
  236:                             (*s_arbre).branches[i] = (struct_arbre *)
  237:                                     (*l_liste_locale).donnee;
  238: 
  239:                             l_ancienne_liste_locale = l_liste_locale;
  240:                             l_liste_locale = (*l_liste_locale).suivant;
  241: 
  242:                             liberation_maillon(s_etat_processus,
  243:                                     l_ancienne_liste_locale);
  244:                         }
  245: 
  246:                         // Introduction de l'arbre dans la pile locale
  247: 
  248:                         l_ancienne_liste_locale = l_liste_locale;
  249: 
  250:                         if ((l_liste_locale = allocation_maillon(
  251:                                 s_etat_processus)) == NULL)
  252:                         {
  253:                             (*s_etat_processus).erreur_systeme =
  254:                                     d_es_allocation_memoire;
  255:                             return(NULL);
  256:                         }
  257: 
  258:                         (*l_liste_locale).suivant = l_ancienne_liste_locale;
  259:                         (*l_liste_locale).donnee = (void *) s_arbre;
  260:                     }
  261: 
  262:                     break;
  263:                 }
  264: 
  265:                 default:
  266:                 {
  267:                     l_ancienne_liste_locale = l_liste_locale;
  268: 
  269:                     if ((l_liste_locale = allocation_maillon(s_etat_processus))
  270:                             == NULL)
  271:                     {
  272:                         (*s_etat_processus).erreur_systeme =
  273:                                 d_es_allocation_memoire;
  274:                         return(NULL);
  275:                     }
  276: 
  277:                     (*l_liste_locale).suivant = l_ancienne_liste_locale;
  278: 
  279:                     if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
  280:                     {
  281:                         (*s_etat_processus).erreur_systeme =
  282:                                 d_es_allocation_memoire;
  283:                         return(NULL);
  284:                     }
  285: 
  286:                     (*s_arbre).feuille = copie_objet(s_etat_processus,
  287:                             (*l_element_courant).donnee, 'P');
  288:                     (*s_arbre).inversion = d_faux;
  289:                     (*s_arbre).nombre_branches = 0;
  290:                     (*s_arbre).branches = NULL;
  291: 
  292:                     (*l_liste_locale).donnee = (void *) s_arbre;
  293:                     break;
  294:                 }
  295:             }
  296: 
  297:             l_element_courant = (*l_element_courant).suivant;
  298:         }
  299: 
  300:         // Toute l'expression a été balayée. On ne doit plus avoir qu'un
  301:         // seul niveau dans la pile locale, ce niveau contenant l'arbre
  302:         // à réduire.
  303: 
  304:         if (l_liste_locale == NULL)
  305:         {
  306:             (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
  307:             return(NULL);
  308:         }
  309:         else if ((*l_liste_locale).suivant != NULL)
  310:         {
  311:             (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
  312:             return(NULL);
  313:         }
  314: 
  315:         s_arbre = (void *) (*l_liste_locale).donnee;
  316: 
  317:         liberation_maillon(s_etat_processus, l_liste_locale);
  318:         l_liste_locale = NULL;
  319: 
  320:         /*
  321:          * Simplification de l'arbre
  322:          */
  323: 
  324: #       ifdef   EXPERIMENTAL_CODE 
  325:         simplification_arbre(s_etat_processus, &s_arbre);
  326: 
  327:         if ((*s_etat_processus).erreur_systeme != d_es)
  328:         {
  329:             return(NULL);
  330:         }
  331: #       endif
  332: 
  333:         /*
  334:          * Transcription de l'arbre q-aire simplifié en expression algébrique.
  335:          * Seule une fonction récursive permet de faire cette conversion
  336:          * simplement.
  337:          */
  338: 
  339:         l_liste_locale = transcription_arbre(s_etat_processus, s_arbre);
  340: 
  341:         if ((s_objet_simplifie = allocation(s_etat_processus, ALG))
  342:                 == NULL)
  343:         {
  344:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  345:             return(NULL);
  346:         }
  347: 
  348:         // Ajout des délimiteurs '<<' et '>>' à la liste d'instructions
  349: 
  350:         if (((*s_objet_simplifie).objet = allocation_maillon(s_etat_processus))
  351:                 == NULL)
  352:         {
  353:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  354:             return(NULL);
  355:         }
  356: 
  357:         l_element_courant = (*s_objet_simplifie).objet;
  358: 
  359:         if (((*l_element_courant).donnee = allocation(s_etat_processus,
  360:                 FCT)) == NULL)
  361:         {
  362:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  363:             return(NULL);
  364:         }
  365: 
  366:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  367:                 .nombre_arguments = 0;
  368:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  369:                 .fonction = instruction_vers_niveau_superieur;
  370: 
  371:         if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  372:                 .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
  373:         {
  374:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  375:             return(NULL);
  376:         }
  377: 
  378:         strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  379:                 .nom_fonction, "<<");
  380: 
  381:         (*l_element_courant).suivant = l_liste_locale;
  382: 
  383:         while((*l_element_courant).suivant != NULL)
  384:         {
  385:             l_element_courant = (*l_element_courant).suivant;
  386:         }
  387: 
  388:         if (((*l_element_courant).suivant =
  389:                 allocation_maillon(s_etat_processus)) == NULL)
  390:         {
  391:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  392:             return(NULL);
  393:         }
  394: 
  395:         l_element_courant = (*l_element_courant).suivant;
  396:         (*l_element_courant).suivant = NULL;
  397: 
  398:         if (((*l_element_courant).donnee = allocation(s_etat_processus,
  399:                 FCT)) == NULL)
  400:         {
  401:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  402:             return(NULL);
  403:         }
  404: 
  405:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  406:                 .nombre_arguments = 0;
  407:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  408:                 .fonction = instruction_vers_niveau_inferieur;
  409: 
  410:         if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  411:                 .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
  412:         {
  413:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  414:             return(NULL);
  415:         }
  416: 
  417:         strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  418:                 .nom_fonction, ">>");
  419:     }
  420:     else
  421:     {
  422:         s_objet_simplifie = copie_objet(s_etat_processus, s_objet, 'P');
  423:     }
  424: 
  425:     return(s_objet_simplifie);
  426: }
  427: 
  428: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>