File:  [local] / rpl / src / calcul_integral.c
Revision 1.74: download - view: text, annotated - select for diffs - revision graph
Wed Jan 17 16:57:09 2024 UTC (3 months, 1 week ago) by bertrand
Branches: MAIN
CVS tags: HEAD
En route pour la 4.1.36.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.36
    4:   Copyright (C) 1989-2024 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 'integrale_romberg'
   29: ================================================================================
   30:   Entrées : pointeur sur une structure struct_processus
   31: --------------------------------------------------------------------------------
   32:   Sorties :
   33: --------------------------------------------------------------------------------
   34:   Effets de bord : néant
   35: ================================================================================
   36: */
   37: 
   38: void
   39: integrale_romberg(struct_processus *s_etat_processus,
   40:         struct_objet *s_expression, unsigned char *variable,
   41:         real8 a, real8 b, real8 precision)
   42: {
   43:     real8                       erreur;
   44:     real8                       h;
   45:     real8                       **t;
   46:     real8                       **t_tampon;
   47:     real8                       *vecteur;
   48:     real8                       *vecteur_precedent;
   49:     real8                       x;
   50: 
   51:     logical1                    validite;
   52:     logical1                    erreur_memoire;
   53: 
   54:     struct_objet                *s_objet;
   55: 
   56:     struct_variable             s_variable;
   57: 
   58:     integer8                    i;
   59:     integer8                    j;
   60:     integer8                    k;
   61:     integer8                    n;
   62:     integer8                    p;
   63:     integer8                    nombre_elements;
   64:     integer8                    nombre_termes;
   65:     integer8                    taille_vecteur_precedent;
   66: 
   67:     erreur = 0;
   68: 
   69:     /*
   70:      * Création d'une variable locale représentant la variable d'intégration
   71:      */
   72: 
   73:     (*s_etat_processus).niveau_courant++;
   74:     s_variable.niveau = (*s_etat_processus).niveau_courant;
   75: 
   76:     if ((s_variable.nom = (unsigned char *) malloc((strlen(variable) + 1) *
   77:             sizeof(unsigned char))) == NULL)
   78:     {
   79:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
   80:         return;
   81:     }
   82: 
   83:     strcpy(s_variable.nom, variable);
   84: 
   85:     if ((s_variable.objet = allocation(s_etat_processus, REL)) == NULL)
   86:     {
   87:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
   88:         return;
   89:     }
   90: 
   91:     if (creation_variable(s_etat_processus, &s_variable, 'V', 'P') == d_erreur)
   92:     {
   93:         return;
   94:     }
   95: 
   96:     /*
   97:      * Algorithme de Romberg
   98:      */
   99: 
  100:     if ((vecteur = (real8 *) malloc(2 * sizeof(real8))) == NULL)
  101:     {
  102:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  103:         return;
  104:     }
  105: 
  106:     evaluation_romberg(s_etat_processus, s_expression, variable, &a,
  107:             &(vecteur[nombre_termes = 0]), &validite);
  108:     nombre_termes += (validite == d_vrai) ? 1 : 0;
  109: 
  110:     evaluation_romberg(s_etat_processus, s_expression, variable, &b,
  111:             &(vecteur[nombre_termes]), &validite);
  112:     nombre_termes += (validite == d_vrai) ? 1 : 0;
  113: 
  114:     if ((t = (real8 **) malloc(sizeof(real8 *))) == NULL)
  115:     {
  116:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  117:         return;
  118:     }
  119: 
  120:     if ((t[0] = (real8 *) malloc(sizeof(real8))) == NULL)
  121:     {
  122:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  123:         return;
  124:     }
  125: 
  126:     t[0][n = 0] = ((b - a) / 2) * sommation_vecteur_reel(vecteur,
  127:             &nombre_termes, &erreur_memoire);
  128: 
  129:     if (erreur_memoire == d_vrai)
  130:     {
  131:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  132:         return;
  133:     }
  134: 
  135:     free(vecteur);
  136: 
  137:     vecteur_precedent = NULL;
  138:     taille_vecteur_precedent = 0;
  139: 
  140:     do
  141:     {
  142:         h = (b - a) / ((real8) (nombre_elements = (((integer8) 1) << (++n))));
  143: 
  144:         if (nombre_elements == 0)
  145:         {
  146:             // Dépassement de capacité
  147:             n--;
  148:             break;
  149:         }
  150: 
  151:         x = a;
  152: 
  153:         /*
  154:          * Nouvelle allocation de t
  155:          */
  156: 
  157:         t_tampon = t;
  158: 
  159:         if ((t = (real8 **) malloc((((size_t) n) + 1) * sizeof(real8 *)))
  160:                 == NULL)
  161:         {
  162:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  163:             return;
  164:         }
  165: 
  166:         for(i = 0; i <= n; i++)
  167:         {
  168:             if ((t[i] = (real8 *) malloc((((size_t) n) + 1) * sizeof(real8)))
  169:                     == NULL)
  170:             {
  171:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  172:                 return;
  173:             }
  174: 
  175:             if (i != n)
  176:             {
  177:                 for(t[i][n] = 0, j = 0; j < n; j++)
  178:                 {
  179:                     t[i][j] = t_tampon[i][j];
  180:                 }
  181:             }
  182:             else
  183:             {
  184:                 for(j = 0; j <= n; t[i][j++] = 0);
  185:             }
  186:         }
  187: 
  188:         for(i = 0; i < n; free(t_tampon[i++]));
  189:         free(t_tampon);
  190: 
  191:         /*
  192:          * Boucle principale
  193:          */
  194: 
  195:         if ((vecteur = (real8 *) malloc((((size_t) nombre_elements) + 1) *
  196:                 sizeof(real8))) == NULL)
  197:         {
  198:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  199:             return;
  200:         }
  201: 
  202:         if (vecteur_precedent == NULL)
  203:         {
  204:             /*
  205:              * Première itération
  206:              */
  207: 
  208:             evaluation_romberg(s_etat_processus, s_expression, variable, &a,
  209:                     &(vecteur[nombre_termes = 0]), &validite);
  210:             nombre_termes += (validite == d_vrai) ? 1 : 0;
  211: 
  212:             evaluation_romberg(s_etat_processus, s_expression, variable, &b,
  213:                     &(vecteur[nombre_termes]), &validite);
  214:             nombre_termes += (validite == d_vrai) ? 1 : 0;
  215: 
  216:             if (nombre_termes == 2)
  217:             {
  218:                 vecteur[0] += vecteur[1];
  219:                 vecteur[0] /= 2;
  220:                 nombre_termes--;
  221:             }
  222: 
  223:             for(i = 1; i < nombre_elements; i++)
  224:             {
  225:                 x += h;
  226: 
  227:                 evaluation_romberg(s_etat_processus, s_expression, variable, &x,
  228:                         &(vecteur[nombre_termes]), &validite);
  229:                 nombre_termes += (validite == d_vrai) ? 1 : 0;
  230:             }
  231:         }
  232:         else
  233:         {
  234:             /*
  235:              * Pour les itérations suivantes, la moitié des points
  236:              * a déjà été calculée.
  237:              */
  238: 
  239:             for(i = 0; i < taille_vecteur_precedent; i++)
  240:             {
  241:                 vecteur[i] = vecteur_precedent[i];
  242:             }
  243: 
  244:             free(vecteur_precedent);
  245: 
  246:             for(nombre_termes = taille_vecteur_precedent, i = 1;
  247:                     i < nombre_elements; x += h, i += 2)
  248:             {
  249:                 x += h;
  250: 
  251:                 evaluation_romberg(s_etat_processus, s_expression, variable, &x,
  252:                         &(vecteur[nombre_termes]), &validite);
  253:                 nombre_termes += (validite == d_vrai) ? 1 : 0;
  254:             }
  255:         }
  256: 
  257:         t[0][n] = h * sommation_vecteur_reel(vecteur, &nombre_termes,
  258:                 &erreur_memoire);
  259: 
  260:         if (erreur_memoire == d_vrai)
  261:         {
  262:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  263:             return;
  264:         }
  265: 
  266:         vecteur_precedent = vecteur;
  267:         taille_vecteur_precedent = nombre_termes;
  268: 
  269:         for(p = 1; p <= n; p++)
  270:         {
  271:             k = n - p;
  272:             t[p][k] = ((pow(4, (real8) p) * t[p - 1][k + 1]) - t[p - 1][k]) /
  273:                     ((real8) (pow(4, (real8) p) - 1));
  274:         }
  275:     } while(((erreur = fabs(t[n][0] - t[n - 1][0])) > precision) &&
  276:             ((*s_etat_processus).var_volatile_requete_arret == 0));
  277: 
  278:     free(vecteur_precedent);
  279: 
  280:     /*
  281:      * Empilement du résultat et liberation de t
  282:      */
  283: 
  284:     if ((s_objet = allocation(s_etat_processus, REL)) == NULL)
  285:     {
  286:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  287:         return;
  288:     }
  289: 
  290:     (*((real8 *) (*s_objet).objet)) = t[n][0];
  291: 
  292:     if (empilement(s_etat_processus, &((*s_etat_processus).l_base_pile),
  293:             s_objet) == d_erreur)
  294:     {
  295:         return;
  296:     }
  297: 
  298:     if ((s_objet = allocation(s_etat_processus, REL)) == NULL)
  299:     {
  300:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  301:         return;
  302:     }
  303: 
  304:     (*((real8 *) (*s_objet).objet)) = erreur;
  305: 
  306:     if (empilement(s_etat_processus, &((*s_etat_processus).l_base_pile),
  307:             s_objet) == d_erreur)
  308:     {
  309:         return;
  310:     }
  311: 
  312:     for(i = 0; i <= n; free(t[i++]));
  313:     free(t);
  314: 
  315:     /*
  316:      * Libération de la variable locale
  317:      */
  318: 
  319:     (*s_etat_processus).niveau_courant--;
  320: 
  321:     if (retrait_variable(s_etat_processus, s_variable.nom, 'L')
  322:             == d_erreur)
  323:     {
  324:         if ((*s_etat_processus).erreur_systeme != d_es)
  325:         {
  326:             if ((*s_etat_processus).erreur_systeme ==
  327:                     d_es_variable_introuvable)
  328:             {
  329:                 (*s_etat_processus).erreur_systeme = d_es;
  330:             }
  331:             else
  332:             {
  333:                 /*
  334:                  * Erreur système
  335:                  */
  336: 
  337:                 return;
  338:             }
  339:         }
  340: 
  341:         (*s_etat_processus).erreur_execution = d_ex_variable_non_definie;
  342:         return;
  343:     }
  344: 
  345:     return;
  346: }
  347: 
  348: 
  349: void
  350: evaluation_romberg(struct_processus *s_etat_processus,
  351:         struct_objet *s_expression, unsigned char *variable, real8 *point,
  352:         real8 *valeur, logical1 *validite)
  353: {
  354:     integer8                            hauteur_pile;
  355: 
  356:     struct_liste_pile_systeme           *l_position_normale;
  357: 
  358:     struct_objet                        *s_objet;
  359: 
  360:     /*
  361:      * Vérification du type de la variable
  362:      */
  363: 
  364:     (*validite) = d_faux;
  365:     (*valeur) = 0;
  366: 
  367:     if (recherche_variable(s_etat_processus, variable) == d_vrai)
  368:     {
  369:         if ((*(*s_etat_processus).pointeur_variable_courante)
  370:                 .variable_verrouillee == d_vrai)
  371:         {
  372:             (*s_etat_processus).erreur_execution = d_ex_variable_verrouillee;
  373:             return;
  374:         }
  375: 
  376:         if ((*(*(*s_etat_processus).pointeur_variable_courante)
  377:                 .objet).type != REL)
  378:         {
  379:             liberation(s_etat_processus, (*(*s_etat_processus)
  380:                     .pointeur_variable_courante).objet);
  381: 
  382:             if (((*(*s_etat_processus).pointeur_variable_courante).objet =
  383:                     allocation(s_etat_processus, REL)) == NULL)
  384:             {
  385:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  386:                 return;
  387:             }
  388:         }
  389: 
  390:         (*((real8 *) (*(*(*s_etat_processus).pointeur_variable_courante)
  391:                 .objet).objet)) = (*point);
  392:     }
  393:     else
  394:     {
  395:         /*
  396:          * La variable d'intégration étant locale, l'utilisateur ne peut
  397:          * pas l'effacer. On ne doit donc jamais passer par ici. Si
  398:          * c'est néanmoins le cas, une erreur système est générée
  399:          * provoquant l'arrêt du programme même dans une
  400:          * structure IFERR.
  401:          */
  402: 
  403:         return;
  404:     }
  405: 
  406:     hauteur_pile = (*s_etat_processus).hauteur_pile_operationnelle;
  407:     l_position_normale = (*s_etat_processus).l_base_pile_systeme;
  408: 
  409:     (*s_etat_processus).erreur_execution = d_ex;
  410:     (*s_etat_processus).exception = d_ep;
  411: 
  412:     if (evaluation(s_etat_processus, s_expression, 'N') == d_erreur)
  413:     {
  414:         if ((*s_etat_processus).erreur_systeme != d_es)
  415:         {
  416:             /*
  417:              * Erreur système
  418:              */
  419: 
  420:             return;
  421:         }
  422:         else
  423:         {
  424:             /*
  425:              * Restauration de la pile initiale
  426:              */
  427: 
  428:             while((*s_etat_processus).hauteur_pile_operationnelle >
  429:                     hauteur_pile)
  430:             {
  431:                 if (depilement(s_etat_processus, &((*s_etat_processus)
  432:                         .l_base_pile), &s_objet) == d_erreur)
  433:                 {
  434:                     (*s_etat_processus).erreur_execution =
  435:                             d_ex_manque_argument;
  436:                     break;
  437:                 }
  438: 
  439:                 liberation(s_etat_processus, s_objet);
  440:             }
  441: 
  442:             /*
  443:              * Restauration de la pile système
  444:              */
  445: 
  446:             while((*s_etat_processus).l_base_pile_systeme !=
  447:                     l_position_normale)
  448:             {
  449:                 depilement_pile_systeme(s_etat_processus);
  450: 
  451:                 if ((*s_etat_processus).erreur_systeme != d_es)
  452:                 {
  453:                     /*
  454:                      * Une pile vide provoque une erreur système
  455:                      */
  456: 
  457:                     return;
  458:                 }
  459:             }
  460:         }
  461: 
  462:         (*s_etat_processus).erreur_execution = d_ex;
  463:         (*s_etat_processus).exception = d_ep;
  464:     }
  465:     else
  466:     {
  467:         /*
  468:          * Retrait de la valeur de la pile
  469:          */
  470: 
  471:         if (depilement(s_etat_processus, &((*s_etat_processus).l_base_pile),
  472:                 &s_objet) == d_erreur)
  473:         {
  474:             (*s_etat_processus).erreur_execution = d_ex_manque_argument;
  475:             return;
  476:         }
  477: 
  478:         if ((*s_objet).type == INT)
  479:         {
  480:             (*valeur) = (real8) (*((integer8 *) (*s_objet).objet));
  481:             (*validite) = d_vrai;
  482:         }
  483:         else if ((*s_objet).type == REL)
  484:         {
  485:             (*valeur) = (*((real8 *) (*s_objet).objet));
  486:             (*validite) = d_vrai;
  487:         }
  488: 
  489:         liberation(s_etat_processus, s_objet);
  490:     }
  491: 
  492:     return;
  493: }
  494: 
  495: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>