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

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

CVSweb interface <joel.bertrand@systella.fr>