Annotation of rpl/src/calcul_integral.c, revision 1.73

1.1       bertrand    1: /*
                      2: ================================================================================
1.72      bertrand    3:   RPL/2 (R) version 4.1.35
1.73    ! bertrand    4:   Copyright (C) 1989-2024 Dr. BERTRAND Joël
1.1       bertrand    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: 
1.11      bertrand   23: #include "rpl-conv.h"
1.1       bertrand   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: 
1.43      bertrand   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;
1.1       bertrand   66: 
1.70      bertrand   67:    erreur = 0;
                     68: 
1.1       bertrand   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:    {
1.43      bertrand  142:        h = (b - a) / ((real8) (nombre_elements = (((integer8) 1) << (++n))));
1.34      bertrand  143: 
1.43      bertrand  144:        if (nombre_elements == 0)
1.34      bertrand  145:        {
                    146:            // Dépassement de capacité
                    147:            n--;
                    148:            break;
                    149:        }
                    150: 
1.1       bertrand  151:        x = a;
                    152: 
                    153:        /*
                    154:         * Nouvelle allocation de t
                    155:         */
                    156: 
                    157:        t_tampon = t;
                    158: 
1.43      bertrand  159:        if ((t = (real8 **) malloc((((size_t) n) + 1) * sizeof(real8 *)))
                    160:                == NULL)
1.1       bertrand  161:        {
                    162:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    163:            return;
                    164:        }
                    165: 
                    166:        for(i = 0; i <= n; i++)
                    167:        {
1.43      bertrand  168:            if ((t[i] = (real8 *) malloc((((size_t) n) + 1) * sizeof(real8)))
                    169:                    == NULL)
1.1       bertrand  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: 
1.43      bertrand  195:        if ((vecteur = (real8 *) malloc((((size_t) nombre_elements) + 1) *
1.1       bertrand  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;
1.43      bertrand  272:            t[p][k] = ((pow(4, (real8) p) * t[p - 1][k + 1]) - t[p - 1][k]) /
                    273:                    ((real8) (pow(4, (real8) p) - 1));
1.1       bertrand  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: {
1.44      bertrand  354:    integer8                            hauteur_pile;
1.1       bertrand  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:    {
1.18      bertrand  369:        if ((*(*s_etat_processus).pointeur_variable_courante)
                    370:                .variable_verrouillee == d_vrai)
1.1       bertrand  371:        {
                    372:            (*s_etat_processus).erreur_execution = d_ex_variable_verrouillee;
                    373:            return;
                    374:        }
                    375: 
1.18      bertrand  376:        if ((*(*(*s_etat_processus).pointeur_variable_courante)
1.1       bertrand  377:                .objet).type != REL)
                    378:        {
1.18      bertrand  379:            liberation(s_etat_processus, (*(*s_etat_processus)
                    380:                    .pointeur_variable_courante).objet);
1.1       bertrand  381: 
1.18      bertrand  382:            if (((*(*s_etat_processus).pointeur_variable_courante).objet =
1.1       bertrand  383:                    allocation(s_etat_processus, REL)) == NULL)
                    384:            {
                    385:                (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    386:                return;
                    387:            }
                    388:        }
                    389: 
1.18      bertrand  390:        (*((real8 *) (*(*(*s_etat_processus).pointeur_variable_courante)
1.1       bertrand  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 >
1.43      bertrand  429:                    hauteur_pile)
1.1       bertrand  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:        {
1.43      bertrand  480:            (*valeur) = (real8) (*((integer8 *) (*s_objet).objet));
1.1       bertrand  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>