File:  [local] / rpl / src / simplification.c
Revision 1.58: download - view: text, annotated - select for diffs - revision graph
Thu Nov 26 11:44:43 2015 UTC (8 years, 5 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_24, HEAD
Mise à jour de Lapack (3.6.0) et du numéro de version du RPL/2.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.24
    4:   Copyright (C) 1989-2015 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:     // Ajout des fonctions
   70: 
   71:     l_liste = (*s_arbre).feuille;
   72: 
   73:     free((*s_arbre).branches);
   74:     free(s_arbre);
   75: 
   76:     // Chaînage des arguments
   77: 
   78:     while(l_pile_locale != NULL)
   79:     {
   80:         l_element_courant = (void *) (*l_pile_locale).donnee;
   81: 
   82:         if (l_element_courant == NULL)
   83:         {
   84:             (*s_etat_processus).erreur_systeme = d_es_pile_vide;
   85:             return(NULL);
   86:         }
   87: 
   88:         while((*l_element_courant).suivant != NULL)
   89:         {
   90:             l_element_courant = (*l_element_courant).suivant;
   91:         }
   92: 
   93:         (*l_element_courant).suivant = l_liste;
   94:         l_liste = (void *) (*l_pile_locale).donnee;
   95: 
   96:         l_nouvelle_pile_locale = (*l_pile_locale).suivant;
   97:         liberation_maillon(s_etat_processus, l_pile_locale);
   98:         l_pile_locale = l_nouvelle_pile_locale;
   99:     }
  100: 
  101:     return(l_liste);
  102: }
  103: 
  104: 
  105: /*
  106: ================================================================================
  107:   Fonction de simplification d'un arbre
  108: ================================================================================
  109:   Entrées : pointeur sur une structure struct_processus
  110: --------------------------------------------------------------------------------
  111:   Sorties :
  112: --------------------------------------------------------------------------------
  113:   Effets de bord : néant
  114: ================================================================================
  115: */
  116: 
  117: static void
  118: inversion_fonctions_arbre(struct_arbre *s_arbre)
  119: {
  120:     return;
  121: }
  122: 
  123: 
  124: static void
  125: simplification_arbre(struct_processus *s_etat_processus,
  126:         struct_arbre *s_arbre)
  127: {
  128:     integer8                i;
  129: 
  130:     if ((*(*(*s_arbre).feuille).donnee).type != FCT)
  131:     {
  132:         // L'objet formant le noeud n'est pas une fonction. Il n'y a aucune
  133:         // simplification possible.
  134: 
  135:         return;
  136:     }
  137: 
  138:     if ((strcmp((*((struct_fonction *) (*(*(*s_arbre).feuille).donnee).objet))
  139:             .nom_fonction, "+") == 0) || (strcmp((*((struct_fonction *)
  140:             (*(*(*s_arbre).feuille).donnee).objet)).nom_fonction, "-") == 0))
  141:     {
  142:         for(i = 0; i < (*s_arbre).nombre_branches; i++)
  143:         {
  144:         }
  145:     }
  146:     else if ((strcmp((*((struct_fonction *) (*(*(*s_arbre).feuille).donnee)
  147:             .objet)).nom_fonction, "*") == 0) || (strcmp((*((struct_fonction *)
  148:             (*(*(*s_arbre).feuille).donnee).objet)).nom_fonction, "/") == 0))
  149:     {
  150:         for(i = 0; i < (*s_arbre).nombre_branches; i++)
  151:         {
  152:         }
  153:     }
  154: 
  155:     return;
  156: }
  157: 
  158: 
  159: /*
  160: ================================================================================
  161:   Fonction 'simplification' (ne libère pas les paramètres)
  162: ================================================================================
  163:   Entrées : pointeur sur une structure struct_processus
  164: --------------------------------------------------------------------------------
  165:   Sorties :
  166: --------------------------------------------------------------------------------
  167:   Effets de bord : néant
  168: ================================================================================
  169: */
  170: 
  171: struct_objet *
  172: simplification(struct_processus *s_etat_processus, struct_objet *s_objet)
  173: {
  174:     struct_objet                *s_objet_simplifie;
  175: 
  176:     integer8                    i;
  177:     integer8                    nombre_arguments;
  178: 
  179:     struct_arbre                *s_arbre;
  180: 
  181:     struct_liste_chainee        *l_element_courant;
  182: 
  183:     // Attention : l_liste_locale et l_ancienne_liste_locale ne contiennent pas
  184:     // un pointeur sur une struct_objet, mais sur une struct_arbre.
  185: 
  186:     struct_liste_chainee        *l_liste_locale;
  187:     struct_liste_chainee        *l_ancienne_liste_locale;
  188: 
  189:     if ((*s_objet).type == ALG)
  190:     {
  191:         /*
  192:          * Transcription de l'expression algébrique en arbre q-aire
  193:          */
  194: 
  195:         l_liste_locale = NULL;
  196:         l_element_courant = (*s_objet).objet;
  197: 
  198:         while(l_element_courant != NULL)
  199:         {
  200:             switch((*(*l_element_courant).donnee).type)
  201:             {
  202:                 // Toutes les fonctions (intrinsèques, extrinsèques et
  203:                 // utilisateurs).
  204: 
  205:                 case FCT:
  206:                 {
  207:                     // Il s'agit d'un objet de type ALG. Nous pouvons donc
  208:                     // sauter les délimiteurs d'expression.
  209: 
  210:                     if ((l_element_courant != (*s_objet).objet) &&
  211:                             ((*l_element_courant).suivant != NULL))
  212:                     {
  213:                         nombre_arguments = (*((struct_fonction *)
  214:                                 (*(*l_element_courant).donnee).objet))
  215:                                 .nombre_arguments;
  216: 
  217:                         // Si le nombre d'arguments vaut 0, la fonction
  218:                         // apparaît en notation algébrique comme une fonction
  219:                         // infixe.
  220: 
  221:                         if (nombre_arguments == 0)
  222:                         {
  223:                             nombre_arguments = 2;
  224:                         }
  225: 
  226:                         if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
  227:                         {
  228:                             (*s_etat_processus).erreur_systeme =
  229:                                     d_es_allocation_memoire;
  230:                             return(NULL);
  231:                         }
  232: 
  233:                         (*s_arbre).nombre_branches = nombre_arguments;
  234: 
  235:                         if (((*s_arbre).feuille = allocation_maillon(
  236:                                 s_etat_processus)) == NULL)
  237:                         {
  238:                             (*s_etat_processus).erreur_systeme =
  239:                                     d_es_allocation_memoire;
  240:                             return(NULL);
  241:                         }
  242: 
  243:                         (*(*s_arbre).feuille).donnee = copie_objet(
  244:                                 s_etat_processus, (*l_element_courant).donnee,
  245:                                 'P');
  246:                         (*(*s_arbre).feuille).suivant = NULL;
  247: 
  248:                         if (((*s_arbre).branches = malloc(((size_t) (*s_arbre)
  249:                                 .nombre_branches) * sizeof(struct_arbre *)))
  250:                                 == NULL)
  251:                         {
  252:                             (*s_etat_processus).erreur_systeme =
  253:                                     d_es_allocation_memoire;
  254:                             return(NULL);
  255:                         }
  256: 
  257:                         for(i = nombre_arguments - 1; i >= 0; i--)
  258:                         {
  259:                             if (l_liste_locale == NULL)
  260:                             {
  261:                                 (*s_etat_processus).erreur_execution =
  262:                                         d_ex_manque_argument;
  263:                                 return(NULL);
  264:                             }
  265: 
  266:                             (*s_arbre).branches[i] = (struct_arbre *)
  267:                                     (*l_liste_locale).donnee;
  268: 
  269:                             l_ancienne_liste_locale = l_liste_locale;
  270:                             l_liste_locale = (*l_liste_locale).suivant;
  271: 
  272:                             liberation_maillon(s_etat_processus,
  273:                                     l_ancienne_liste_locale);
  274:                         }
  275: 
  276:                         // Introduction de l'arbre dans la pile locale
  277: 
  278:                         l_ancienne_liste_locale = l_liste_locale;
  279: 
  280:                         if ((l_liste_locale = allocation_maillon(
  281:                                 s_etat_processus)) == NULL)
  282:                         {
  283:                             (*s_etat_processus).erreur_systeme =
  284:                                     d_es_allocation_memoire;
  285:                             return(NULL);
  286:                         }
  287: 
  288:                         (*l_liste_locale).suivant = l_ancienne_liste_locale;
  289:                         (*l_liste_locale).donnee = (void *) s_arbre;
  290:                     }
  291: 
  292:                     break;
  293:                 }
  294: 
  295:                 default:
  296:                 {
  297:                     l_ancienne_liste_locale = l_liste_locale;
  298: 
  299:                     if ((l_liste_locale = allocation_maillon(s_etat_processus))
  300:                             == NULL)
  301:                     {
  302:                         (*s_etat_processus).erreur_systeme =
  303:                                 d_es_allocation_memoire;
  304:                         return(NULL);
  305:                     }
  306: 
  307:                     (*l_liste_locale).suivant = l_ancienne_liste_locale;
  308: 
  309:                     if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
  310:                     {
  311:                         (*s_etat_processus).erreur_systeme =
  312:                                 d_es_allocation_memoire;
  313:                         return(NULL);
  314:                     }
  315: 
  316:                     if (((*s_arbre).feuille = allocation_maillon(
  317:                             s_etat_processus)) == NULL)
  318:                     {
  319:                         (*s_etat_processus).erreur_systeme =
  320:                                 d_es_allocation_memoire;
  321:                         return(NULL);
  322:                     }
  323: 
  324:                     (*(*s_arbre).feuille).donnee = copie_objet(
  325:                             s_etat_processus, (*l_element_courant).donnee, 'P');
  326:                     (*(*s_arbre).feuille).suivant = NULL;
  327:                     (*s_arbre).nombre_branches = 0;
  328:                     (*s_arbre).branches = NULL;
  329: 
  330:                     (*l_liste_locale).donnee = (void *) s_arbre;
  331:                     break;
  332:                 }
  333:             }
  334: 
  335:             l_element_courant = (*l_element_courant).suivant;
  336:         }
  337: 
  338:         // Toute l'expression a été balayée. On ne doit plus avoir qu'un
  339:         // seul niveau dans la pile locale, ce niveau contenant l'arbre
  340:         // à réduire.
  341: 
  342:         if (l_liste_locale == NULL)
  343:         {
  344:             (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
  345:             return(NULL);
  346:         }
  347:         else if ((*l_liste_locale).suivant != NULL)
  348:         {
  349:             (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
  350:             return(NULL);
  351:         }
  352: 
  353:         s_arbre = (void *) (*l_liste_locale).donnee;
  354: 
  355:         liberation_maillon(s_etat_processus, l_liste_locale);
  356:         l_liste_locale = NULL;
  357: 
  358:         /*
  359:          * Simplification de l'arbre
  360:          */
  361: 
  362: #       ifdef   EXPERIMENTAL_CODE 
  363:         simplification_arbre(s_etat_processus, s_arbre);
  364: 
  365:         if ((*s_etat_processus).erreur_systeme != d_es)
  366:         {
  367:             return(NULL);
  368:         }
  369: #       endif
  370: 
  371:         /*
  372:          * Transcription de l'arbre q-aire simplifié en expression algébrique.
  373:          * Seule une fonction récursive permet de faire cette conversion
  374:          * simplement.
  375:          */
  376: 
  377:         l_liste_locale = transcription_arbre(s_etat_processus, s_arbre);
  378: 
  379:         if ((s_objet_simplifie = allocation(s_etat_processus, ALG))
  380:                 == NULL)
  381:         {
  382:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  383:             return(NULL);
  384:         }
  385: 
  386:         // Ajout des délimiteurs '<<' et '>>' à la liste d'instructions
  387: 
  388:         if (((*s_objet_simplifie).objet = allocation_maillon(s_etat_processus))
  389:                 == NULL)
  390:         {
  391:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  392:             return(NULL);
  393:         }
  394: 
  395:         l_element_courant = (*s_objet_simplifie).objet;
  396: 
  397:         if (((*l_element_courant).donnee = allocation(s_etat_processus,
  398:                 FCT)) == NULL)
  399:         {
  400:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  401:             return(NULL);
  402:         }
  403: 
  404:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  405:                 .nombre_arguments = 0;
  406:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  407:                 .fonction = instruction_vers_niveau_superieur;
  408: 
  409:         if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  410:                 .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
  411:         {
  412:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  413:             return(NULL);
  414:         }
  415: 
  416:         strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  417:                 .nom_fonction, "<<");
  418: 
  419:         (*l_element_courant).suivant = l_liste_locale;
  420: 
  421:         while((*l_element_courant).suivant != NULL)
  422:         {
  423:             l_element_courant = (*l_element_courant).suivant;
  424:         }
  425: 
  426:         if (((*l_element_courant).suivant =
  427:                 allocation_maillon(s_etat_processus)) == NULL)
  428:         {
  429:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  430:             return(NULL);
  431:         }
  432: 
  433:         l_element_courant = (*l_element_courant).suivant;
  434:         (*l_element_courant).suivant = NULL;
  435: 
  436:         if (((*l_element_courant).donnee = allocation(s_etat_processus,
  437:                 FCT)) == NULL)
  438:         {
  439:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  440:             return(NULL);
  441:         }
  442: 
  443:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  444:                 .nombre_arguments = 0;
  445:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  446:                 .fonction = instruction_vers_niveau_inferieur;
  447: 
  448:         if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  449:                 .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
  450:         {
  451:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  452:             return(NULL);
  453:         }
  454: 
  455:         strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  456:                 .nom_fonction, ">>");
  457:     }
  458:     else
  459:     {
  460:         s_objet_simplifie = copie_objet(s_etat_processus, s_objet, 'P');
  461:     }
  462: 
  463:     return(s_objet_simplifie);
  464: }
  465: 
  466: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>