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

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

CVSweb interface <joel.bertrand@systella.fr>