File:  [Repository ATC2] / ADD_ver_10 / Source Code / Source Files / CalculosMatrices.c
Revision 1.2: download - view: text, annotated - select for diffs
Tue Feb 28 14:54:21 2006 UTC (18 years, 6 months ago) by rico
Branches: MAIN
CVS tags: HEAD
*** empty log message ***

/********************************************************************/
/*  CalculosMatrices.c                                              */
/*                                                                  */
/*                                                                  */
/*  Copyright (c) 1997-2006 Rafael Rico      (rafael.rico@uah.es)   */
/*                                                                  */
/*  Este fichero forma parte de ADD                                 */
/*  (Analizador de Dependencias de Datos)                           */
/*  Version 5.10.                                                   */
/*                                                                  */
/*                                                                  */
/*  ADD es software libre. Puede redistribuirlo y/o modificarlo     */
/*  bajo los términos de la Licencia Pública General de GNU         */
/*  según es publicada por la Free Software Foundation, bien bajo   */
/*  la versión 2 de dicha Licencia o bien (según su elección)       */
/*  bajo cualquier versión posterior.                               */
/*                                                                  */
/*  ADD se distribuye con la esperanza de que sea útil,             */
/*  pero SIN NINGUNA GARANTÍA, incluso sin la garantía MERCANTIL    */
/*  implícita y sin garantizar la CONVENIENCIA PARA UN PROPÓSITO    */
/*  PARTICULAR. Véase la Licencia Pública General de GNU para       */
/*  más detalles.                                                   */
/*                                                                  */
/*  Debería haber recibido una copia de la Licencia Pública General */
/*  junto con ADD. Si no ha sido así, escriba a la Free Software    */
/*  Foundation, Inc., 51 Franklin St, Fifth Floor,                  */
/*  Boston, MA  02110-1301  EEUU.                                   */
/*                                                                  */
/*  -------------------------- Historia --------------------------- */
/*                                                                  */
/*  $Id: CalculosMatrices.c,v 1.2 2006/02/28 14:54:21 rico Exp $                                                            */
/*                                                                  */
/*  Revisión 1.2. 01/2006                                           */
/*  Se añade la licencia GPL y documentación en estilo Javadoc      */
/*                                                                  */
/*  Revisión 1.1. 09/2005                                           */
/*  Versión inicial                                                 */
/*                                                                  */
/********************************************************************/

/******************************************************************************/
/* MÓDULO: CalculosMatrices.c                                                 */
/*                                                                            */
/* Este módulo contiene las funciones que realizan cálculos sobre             */
/* las matrices.                                                              */
/******************************************************************************/
/* Fecha: 26 de septiembre de 2005                                            */
/******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "defines.h"
#include "tipos.h"
#include "calculosmatrices.h"

/* configuración */
extern struct argumentos configuracion;

/* análisis de dependencias de datos */
extern struct punterosD matriz;
extern unsigned char **matrizC;
extern char **OrdenParcial;

/* parámetros asociados a las matrices */
extern parametromatriz *pasos;
extern parametromatriz *mediapasos;
extern parametromatriz *grado;
extern parametromatriz *mediagrado;
extern parametromatriz *acoplo;
extern parametromatriz *mediaacoplo;

/* otros resultados */
extern unsigned long *distribucionpasos;


/* esta función calcula la matriz de caminos de dependencias C */
/* a partir de una matriz de dependencias D */
/* devuelve el número de pasos de computación requeridos para */
/* finalizar la computación de la secuencia expresada por D */
/* (la matriz de caminos devuelta no ha sido reducida a 0s y 1s) */

/* esta función es muy consumidora de tiempo ya que calcula potencias de D */

unsigned int CalcularMatrizCaminos(unsigned char **D, unsigned char **C)
{
    char mensaje[MAX_LINE];
    unsigned char *v;        /* vector temporal */
    unsigned char **tmp;    /* matriz temporal */

    unsigned int i, j, k, potencia;
    unsigned int suma;
    unsigned char matriz_nula;


    if(D == NULL)
    {
        sprintf(mensaje, "[CalcularMatrizCaminos] La matriz D indicada no existe");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
    }

    /* necesito un vector y una matriz temporal de 'unsigned char' */
    /* para calcular las sucesivas potencias de la matriz D */

    /* hago la reserva de memoria para el vector */
    v = calloc(configuracion.ventana , sizeof(unsigned char *));
    if (v == NULL)
    {
        sprintf(mensaje, "[CalcularMatrizCaminos] Memoria insuficiente");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
        /* el programa finaliza si no hay memoria suficiente */
    }

    /* hago la reserva de memoria para la matriz */
    /* 1º un puntero por cada fila */
    tmp = calloc(configuracion.ventana , sizeof(unsigned char *));
    if (tmp == NULL)
    {
        sprintf(mensaje, "[CalcularMatrizCaminos] Memoria insuficiente");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
        /* el programa finaliza si no hay memoria suficiente */
    }
    /* 2º un 'char' por cada columna */
    for(i=0; i<configuracion.ventana; i++)
    {
        tmp[i] = calloc(configuracion.ventana, sizeof(unsigned char));
        if (tmp[i] == NULL)
        {
            sprintf(mensaje, "[CalcularMatrizCaminos] Memoria insuficiente");
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
            /* el programa finaliza si no hay memoria suficiente */
        }
    }


    /* inicio la matriz temporal con la matriz 'identidad' (1s en la diagonal) */
    /* al reservar con 'calloc' se rellena con 0s */

    for(i=0; i<configuracion.ventana; i++) tmp[i][i] = 1;


    /* calculo sucesivas potencias de la matriz 'D' hasta que se anule */
    /* utilizo la expresión TMP * D = TMP */
    /* el uso del vector me permite escribir el resultado sobre 'TMP' */
    for(potencia=0; potencia<configuracion.ventana; potencia++)
    {
        for(i=0; i<configuracion.ventana; i++)
        {
              for(k=0; k<configuracion.ventana; k++) v[k]=tmp[i][k];
            for(j=0; j<configuracion.ventana; j++)
            {
                suma = 0;
                for(k=0; k<configuracion.ventana; k++)
                {
                    suma += v[k] * D[k][j];
                }
                tmp[i][j] = suma;
            }
        }

        /* la matriz 'TMP' contiene la n-ésima+1 potencia de 'D' */

        /* ahora evalúo si el resultado es la matriz nula */
        /* si es así no tengo que continuar ya que no hay */
        /* caminos de dependencias de longitud mayor */

        matriz_nula = SI;
        for(i=0; i<configuracion.ventana; i++)
        {
            for(j=0; j<configuracion.ventana; j++)
            {
                if(tmp[i][j] != 0) {matriz_nula = NO; break;}
            }
            if(matriz_nula == NO) break;
        }
        if(matriz_nula == SI) break;

        /* sumo la nueva potencia de la matriz de dependencias D^^p */
        /* a la matriz de caminos parcial 'C' si me han pasado un puntero no nulo */
        if(*C != NULL)
        {
            for(i=0; i<configuracion.ventana; i++)
            {
                for(j=0; j<configuracion.ventana; j++) C[i][j] += tmp[i][j];
            }
        }
    }

    /* libero la memoria reservada anteriormente */
    /* libero el vector */
    free(v);
    /* libero la matriz */
    for(i=0; i<configuracion.ventana; i++) free(tmp[i]); free(tmp);

    return potencia+1;    /* devuelve el rango de la primera potencia nula de 'D' */
}


/* esta función establece la lista del orden parcial contenido en D */
/* y devuelve el número de pasos de computación del camino crítico */
/* si le pasamos un puntero NULO en el parámetro lista sólo realiza el */
/* calculo de pasos de computación (método más rápido que el anterior) */
/* se asume que la matriz D no ha sido reducida a 0s y 1s */

unsigned int ListaOrdenParcial(unsigned char **D, char **lista)
{
    char mensaje[MAX_LINE];
    unsigned char *lanzadas;    /* vector de instrucciones lanzadas */
    unsigned char **tmp;        /* matriz temporal */

    unsigned int pasos, procesadas;
    unsigned int i, j;
    char cadena[6];        /* cadena para pasar enteros a strings */


    if(D == NULL)
    {
        sprintf(mensaje, "[ListaOrdenParcial] La matriz D indicada no existe");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
    }

    /* necesito un vector y una matriz temporal de 'unsigned char' */
    /* para calcular las sucesivas potencias de la matriz D */

    /* hago la reserva de memoria para el vector */
    lanzadas = calloc(configuracion.ventana , sizeof(unsigned char *));
    if (lanzadas == NULL)
    {
        sprintf(mensaje, "[ListaOrdenParcial] Memoria insuficiente");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
        /* el programa finaliza si no hay memoria suficiente */
    }

    /* hago la reserva de memoria para la matriz */
    /* 1º un puntero por cada fila */
    tmp = calloc(configuracion.ventana , sizeof(unsigned char *));
    if (tmp == NULL)
    {
        sprintf(mensaje, "[ListaOrdenParcial] Memoria insuficiente");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
        /* el programa finaliza si no hay memoria suficiente */
    }
    /* 2º un 'char' por cada columna */
    for(i=0; i<configuracion.ventana; i++)
    {
        tmp[i] = calloc(configuracion.ventana, sizeof(unsigned char));
        if (tmp[i] == NULL)
        {
            sprintf(mensaje, "[ListaOrdenParcial] Memoria insuficiente");
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
            /* el programa finaliza si no hay memoria suficiente */
        }
    }

    /* copio la matriz de dependencias D sobre la temporal */
    for(i=0; i<configuracion.ventana; i++)
    {
        for(j=0; j<configuracion.ventana; j++) tmp[i][j] = D[i][j];
    }
    
    /* pongo a cero el vector de lanzadas */
    for(i=0; i<configuracion.ventana; i++) lanzadas[i] = 0;

    /* inicio el contador de pasos de computaci¢n */
    pasos = 0;

    /* inicio el contador de instrucciones procesadas */
    procesadas = 0;


    while(configuracion.ventana - procesadas)
    {
        pasos++;

        /* busco tareas independientes entre las NO lanzadas */
        for(i=0; i<configuracion.ventana; i++)
        {
            if(lanzadas[i]==0)    /* si es 0 significa que no se ha lanzado */
            {
                   /* miro si el vector de dependencias es nulo */
                for(j=0; j<i; j++)
                {
                    if(tmp[i][j]!=0) break;
                }
                if(j==i)
                {
                    lanzadas[i]=1; /* la instrucci¢n es independiente */

                    /* anoto la instrucción en la lista del orden parcial */
                    /* en el paso de computación en curso */
                    if(lista != NULL)
                    {
                        sprintf(cadena, "%u", i);
                        AgregarElementoLista(lista[pasos-1], cadena);
                    }
                }
            }
        }

        /* ahora actualizo la matriz de dependencias con la lista de */
        /* instrucciones independientes que han sido lanzadas */

        for(i=0; i<configuracion.ventana; i++)
        {
            if(lanzadas[i]==1)    /* si es 1 significa que es independiente */
            {
                for(j=i+1; j<configuracion.ventana; j++)
                {
                    if(tmp[j][i]!=0) tmp[j][i]=0;
                }
            }
        }

        /* ahora actualizo el vector de lanzadas */
        for(i=0; i<configuracion.ventana; i++)
        {
            if(lanzadas[i]==1)
            {
                lanzadas[i]=2; /* significa que ha sido procesada */
                   procesadas++;
            }
        }
    }

    /* libero la memoria reservada anteriormente */
    /* libero el vector */
    free(lanzadas);
    /* libero la matriz */
    for(i=0; i<configuracion.ventana; i++) free(tmp[i]); free(tmp);

    return pasos;
}


/* esta función determina el 'acoplamiento' de una matriz de dependencias de datos */

unsigned int Acoplamiento(unsigned char **D)
{
    char mensaje[MAX_LINE];
    unsigned int i, j;
    unsigned int acoplo = 0;

    if(D == NULL)
    {
        sprintf(mensaje, "[Acoplamiento] La matriz D indicada no existe");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
    }

    /* puesto que las matrices se obtienen de la secuencia de código */
    /* estamos seguros de que son canónicas y, por tanto, no es necesario */
    /* hacer el recorrido completo de todas sus componentes */
    /* basta con empezar en la instrucción 1 y recorres columnas hasta la diagonal */
    for(i=1; i<configuracion.ventana; i++)
    {
        for(j=0; j<i; j++) if(D[i][j] != 0) acoplo++;
    }

    return acoplo;
}



/* esta función reserva memoria para un array de 'num_cadenas' de punteros /*
/* a cadenas de caracteres de tamaño fijo 'tamano' y devuelve el puntero */

/* con esta estructura implantaremos la lista de orden parcial */
/* trabajando con punteros a char y cadenas de tamaño variable puede */
/* ser más eficaz pero es necesario ser más cuidadoso */

char ** CrearArrayStrings(unsigned int num_cadenas, unsigned int tamano)
{
    char mensaje[MAX_LINE];
    unsigned int i;
    char **listado;

    /* 1º un puntero por cada fila */
    listado = calloc(num_cadenas, sizeof(char *));
    if (listado == NULL)
    {
        sprintf(mensaje, "[CrearArrayStrings] Memoria insuficiente");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
        /* el programa finaliza si no hay memoria suficiente */
    }
    /* 2º cuatro 'char' por cada columna (3 caracteres de número y un separador ':') */
    for(i=0; i<configuracion.ventana; i++)
    {
        listado[i] = calloc(tamano, sizeof(char));
        if (listado[i] == NULL)
        {
            sprintf(mensaje, "[CrearArrayStrings] Memoria insuficiente");
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
            /* el programa finaliza si no hay memoria suficiente */
        }
    }
    return listado;
}


/* reserva memoria para construir un listado de orden parcial: */
/* cada línea del listado corresponde a un paso de computación */
/* y cada paso de computación contiene una cadena con la lista */
/* de instrucciones sin dependencias de datos en ese momento */

void CrearListaOrdenParcial()
{
    unsigned int dim;

    dim = configuracion.ventana;

    OrdenParcial = CrearArrayStrings(dim, 4*dim);
}


/* inicia el listado de orden parcial rellenando con la cadena vacía '\0' */

void IniciarListaOrdenParcial()
{
    unsigned int i, dim;

    dim = configuracion.ventana;
    
    if(OrdenParcial != NULL) for(i=0; i<dim; i++) *OrdenParcial[i] = '\0'; 
}


/* libera la memoria reservada para el listado de orden parcial */

void LiberarMemoriaListaOrdenParcial()
{
    unsigned int i,dim;

    dim = configuracion.ventana;

    if(OrdenParcial != NULL)
    {
        for(i=0; i<dim; i++)
        {
            free(OrdenParcial[i]); 
        }
        free(OrdenParcial);
    }
}


/* crea la matriz de caminos de dependencias */

void CrearMatrizCaminos()
{
    matrizC = CrearMatriz();
}


/* inicia la matriz de caminos de dependencias */

void IniciarMatrizCaminos()
{
    IniciarMatriz(matrizC);
}


/* libera la memoria de la matriz de caminos */

void LiberarMemoriaMatrizCaminos()
{
    LiberarMemoriaMatriz(matrizC);
}


/* reserva espacio en memoria para una variable agregada */

parametromatriz * CrearVariableAgregada()
{
    char mensaje[MAX_LINE];
    parametromatriz *variable;
    
    variable = calloc(1, sizeof(parametromatriz));
    if (variable == NULL)
    {
        sprintf(mensaje, "[CrearVariableAgragada] Memoria insuficiente");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
        /* el programa finaliza si no hay memoria suficiente */
    }

    return variable;
}


/* inicia a 0 una variable agregada */

void IniciarVariableAgregada(parametromatriz *variable)
{
    variable->Ddatoexp = 0.0;
    variable->Ddir_exp = 0.0;
    variable->Dpilaexp = 0.0; 
    variable->Destadoexp = 0.0; 
        
    variable->Ddatoimp = 0.0; 
    variable->Ddir_imp = 0.0; 
    variable->Dpilaimp = 0.0; 
    variable->Destadoimp = 0.0; 

    variable->ADdatoexp = 0.0; 
    variable->ADdir_exp = 0.0; 
    variable->ADpilaexp = 0.0; 
    variable->ADestadoexp = 0.0; 
        
    variable->ADdatoimp = 0.0; 
    variable->ADdir_imp = 0.0; 
    variable->ADpilaimp = 0.0; 
    variable->ADestadoimp = 0.0; 

    variable->Sdatoexp = 0.0; 
    variable->Sdir_exp = 0.0; 
    variable->Spilaexp = 0.0; 
    variable->Sestadoexp = 0.0; 
        
    variable->Sdatoimp = 0.0; 
    variable->Sdir_imp = 0.0; 
    variable->Spilaimp = 0.0; 
    variable->Sestadoimp = 0.0; 

    variable->D = 0.0; 
}



/* esta función calcula el nuevo promedio de una variable agregada (media) a partir del */
/* índice (n) y del valor actual o en curso de esa variable (actual) */

/*
void CalcularPromedioVariableAgregada(parametromatriz *media, parametromatriz *actual, unsigned long n)
{
    if(matriz.Ddatoexp != NULL) media->Ddatoexp = ((n - 1) * media->Ddatoexp + actual->Ddatoexp) / n;
    if(matriz.Ddir_exp != NULL) media->Ddir_exp = ((n - 1) * media->Ddir_exp + actual->Ddir_exp) / n;
    if(matriz.Dpilaexp != NULL) media->Dpilaexp = ((n - 1) * media->Dpilaexp + actual->Dpilaexp) / n; 
    if(matriz.Destadoexp != NULL) media->Destadoexp = ((n - 1) * media->Destadoexp + actual->Destadoexp) / n; 
        
    if(matriz.Ddatoimp != NULL) media->Ddatoimp = ((n - 1) * media->Ddatoimp + actual->Ddatoimp) / n; 
    if(matriz.Ddir_imp != NULL) media->Ddir_imp = ((n - 1) * media->Ddir_imp + actual->Ddir_imp) / n; 
    if(matriz.Dpilaimp != NULL) media->Dpilaimp = ((n - 1) * media->Dpilaimp + actual->Dpilaimp) / n; 
    if(matriz.Destadoimp != NULL) media->Destadoimp = ((n - 1) * media->Destadoimp + actual->Destadoimp) / n; 

    if(matriz.ADdatoexp != NULL) media->ADdatoexp = ((n - 1) * media->ADdatoexp + actual->ADdatoexp) / n; 
    if(matriz.ADdir_exp != NULL) media->ADdir_exp = ((n - 1) * media->ADdir_exp + actual->ADdir_exp) / n; 
    if(matriz.ADpilaexp != NULL) media->ADpilaexp = ((n - 1) * media->ADpilaexp + actual->ADpilaexp) / n; 
    if(matriz.ADestadoexp != NULL) media->ADestadoexp = ((n - 1) * media->ADestadoexp + actual->ADestadoexp) / n; 
        
    if(matriz.ADdatoimp != NULL) media->ADdatoimp = ((n - 1) * media->ADdatoimp + actual->ADdatoimp) / n; 
    if(matriz.ADdir_imp != NULL) media->ADdir_imp = ((n - 1) * media->ADdir_imp + actual->ADdir_imp) / n; 
    if(matriz.ADpilaimp != NULL) media->ADpilaimp = ((n - 1) * media->ADpilaimp + actual->ADpilaimp) / n; 
    if(matriz.ADestadoimp != NULL) media->ADestadoimp = ((n - 1) * media->ADestadoimp + actual->ADestadoimp) / n; 

    if(matriz.Sdatoexp != NULL) media->Sdatoexp = ((n - 1) * media->Sdatoexp + actual->Sdatoexp) / n; 
    if(matriz.Sdir_exp != NULL) media->Sdir_exp = ((n - 1) * media->Sdir_exp + actual->Sdir_exp) / n; 
    if(matriz.Spilaexp != NULL) media->Spilaexp = ((n - 1) * media->Spilaexp + actual->Spilaexp) / n; 
    if(matriz.Sestadoexp != NULL) media->Sestadoexp = ((n - 1) * media->Sestadoexp + actual->Sestadoexp) / n; 
        
    if(matriz.Sdatoimp != NULL) media->Sdatoimp = ((n - 1) * media->Sdatoimp + actual->Sdatoimp) / n; 
    if(matriz.Sdir_imp != NULL) media->Sdir_imp = ((n - 1) * media->Sdir_imp + actual->Sdir_imp) / n; 
    if(matriz.Spilaimp != NULL) media->Spilaimp = ((n - 1) * media->Spilaimp + actual->Spilaimp) / n; 
    if(matriz.Sestadoimp != NULL) media->Sestadoimp = ((n - 1) * media->Sestadoimp + actual->Sestadoimp) / n; 

    if(matriz.D != NULL) media->D = ((n - 1) * media->D + actual->D) / n; 
}
*/


/* utilizando la función: */
/* double CalcularNuevoPromedio (double promedioanterior, double valoractual, unsigned long n)
/* es más compacto aunque quizá algo más lento */

void CalcularPromedioVariableAgregada(parametromatriz *media, parametromatriz *actual, unsigned long n)
{
    if(matriz.Ddatoexp != NULL) media->Ddatoexp = CalcularNuevoPromedio(media->Ddatoexp, actual->Ddatoexp, n);
    if(matriz.Ddir_exp != NULL) media->Ddir_exp = CalcularNuevoPromedio(media->Ddir_exp, actual->Ddir_exp, n);
    if(matriz.Dpilaexp != NULL) media->Dpilaexp = CalcularNuevoPromedio(media->Dpilaexp, actual->Dpilaexp, n); 
    if(matriz.Destadoexp != NULL) media->Destadoexp = CalcularNuevoPromedio(media->Destadoexp, actual->Destadoexp, n); 
        
    if(matriz.Ddatoimp != NULL) media->Ddatoimp = CalcularNuevoPromedio(media->Ddatoimp, actual->Ddatoimp, n); 
    if(matriz.Ddir_imp != NULL) media->Ddir_imp = CalcularNuevoPromedio(media->Ddir_imp, actual->Ddir_imp, n); 
    if(matriz.Dpilaimp != NULL) media->Dpilaimp = CalcularNuevoPromedio(media->Dpilaimp, actual->Dpilaimp, n); 
    if(matriz.Destadoimp != NULL) media->Destadoimp = CalcularNuevoPromedio(media->Destadoimp, actual->Destadoimp, n); 

    if(matriz.ADdatoexp != NULL) media->ADdatoexp = CalcularNuevoPromedio(media->ADdatoexp, actual->ADdatoexp, n); 
    if(matriz.ADdir_exp != NULL) media->ADdir_exp = CalcularNuevoPromedio(media->ADdir_exp, actual->ADdir_exp, n); 
    if(matriz.ADpilaexp != NULL) media->ADpilaexp = CalcularNuevoPromedio(media->ADpilaexp, actual->ADpilaexp, n); 
    if(matriz.ADestadoexp != NULL) media->ADestadoexp = CalcularNuevoPromedio(media->ADestadoexp, actual->ADestadoexp, n); 
        
    if(matriz.ADdatoimp != NULL) media->ADdatoimp = CalcularNuevoPromedio(media->ADdatoimp, actual->ADdatoimp, n); 
    if(matriz.ADdir_imp != NULL) media->ADdir_imp = CalcularNuevoPromedio(media->ADdir_imp, actual->ADdir_imp, n); 
    if(matriz.ADpilaimp != NULL) media->ADpilaimp = CalcularNuevoPromedio(media->ADpilaimp, actual->ADpilaimp, n); 
    if(matriz.ADestadoimp != NULL) media->ADestadoimp = CalcularNuevoPromedio(media->ADestadoimp, actual->ADestadoimp, n); 

    if(matriz.Sdatoexp != NULL) media->Sdatoexp = CalcularNuevoPromedio(media->Sdatoexp, actual->Sdatoexp, n); 
    if(matriz.Sdir_exp != NULL) media->Sdir_exp = CalcularNuevoPromedio(media->Sdir_exp, actual->Sdir_exp, n); 
    if(matriz.Spilaexp != NULL) media->Spilaexp = CalcularNuevoPromedio(media->Spilaexp, actual->Spilaexp, n); 
    if(matriz.Sestadoexp != NULL) media->Sestadoexp = CalcularNuevoPromedio(media->Sestadoexp, actual->Sestadoexp, n); 
        
    if(matriz.Sdatoimp != NULL) media->Sdatoimp = CalcularNuevoPromedio(media->Sdatoimp, actual->Sdatoimp, n); 
    if(matriz.Sdir_imp != NULL) media->Sdir_imp = CalcularNuevoPromedio(media->Sdir_imp, actual->Sdir_imp, n); 
    if(matriz.Spilaimp != NULL) media->Spilaimp = CalcularNuevoPromedio(media->Spilaimp, actual->Spilaimp, n); 
    if(matriz.Sestadoimp != NULL) media->Sestadoimp = CalcularNuevoPromedio(media->Sestadoimp, actual->Sestadoimp, n); 

    if(matriz.D != NULL) media->D = CalcularNuevoPromedio(media->D, actual->D, n); 
}


/* esta función calcula los pasos de computación de cada matriz de dependencias */

/* para calcular los pasos de computación se usa el método más rápido, es decir, */
/* construir la lista de orden parcial... aunque no se anote ya que pasamos un puntero nulo */

void CalcularPasosComputacion(parametromatriz *pasos)
{
    if(matriz.Ddatoexp != NULL) pasos->Ddatoexp = ListaOrdenParcial(matriz.Ddatoexp, NULL);
    if(matriz.Ddir_exp != NULL) pasos->Ddir_exp = ListaOrdenParcial(matriz.Ddir_exp, NULL);
    if(matriz.Dpilaexp != NULL) pasos->Dpilaexp = ListaOrdenParcial(matriz.Dpilaexp, NULL); 
    if(matriz.Destadoexp != NULL) pasos->Destadoexp = ListaOrdenParcial(matriz.Destadoexp, NULL); 
        
    if(matriz.Ddatoimp != NULL) pasos->Ddatoimp = ListaOrdenParcial(matriz.Ddatoimp, NULL); 
    if(matriz.Ddir_imp != NULL) pasos->Ddir_imp = ListaOrdenParcial(matriz.Ddir_imp, NULL); 
    if(matriz.Dpilaimp != NULL) pasos->Dpilaimp = ListaOrdenParcial(matriz.Dpilaimp, NULL); 
    if(matriz.Destadoimp != NULL) pasos->Destadoimp = ListaOrdenParcial(matriz.Destadoimp, NULL); 

    if(matriz.ADdatoexp != NULL) pasos->ADdatoexp = ListaOrdenParcial(matriz.ADdatoexp, NULL); 
    if(matriz.ADdir_exp != NULL) pasos->ADdir_exp = ListaOrdenParcial(matriz.ADdir_exp, NULL); 
    if(matriz.ADpilaexp != NULL) pasos->ADpilaexp = ListaOrdenParcial(matriz.ADpilaexp, NULL); 
    if(matriz.ADestadoexp != NULL) pasos->ADestadoexp = ListaOrdenParcial(matriz.ADestadoexp, NULL); 
        
    if(matriz.ADdatoimp != NULL) pasos->ADdatoimp = ListaOrdenParcial(matriz.ADdatoimp, NULL); 
    if(matriz.ADdir_imp != NULL) pasos->ADdir_imp = ListaOrdenParcial(matriz.ADdir_imp, NULL); 
    if(matriz.ADpilaimp != NULL) pasos->ADpilaimp = ListaOrdenParcial(matriz.ADpilaimp, NULL); 
    if(matriz.ADestadoimp != NULL) pasos->ADestadoimp = ListaOrdenParcial(matriz.ADestadoimp, NULL); 

    if(matriz.Sdatoexp != NULL) pasos->Sdatoexp = ListaOrdenParcial(matriz.Sdatoexp, NULL); 
    if(matriz.Sdir_exp != NULL) pasos->Sdir_exp = ListaOrdenParcial(matriz.Sdir_exp, NULL); 
    if(matriz.Spilaexp != NULL) pasos->Spilaexp = ListaOrdenParcial(matriz.Spilaexp, NULL); 
    if(matriz.Sestadoexp != NULL) pasos->Sestadoexp = ListaOrdenParcial(matriz.Sestadoexp, NULL); 
        
    if(matriz.Sdatoimp != NULL) pasos->Sdatoimp = ListaOrdenParcial(matriz.Sdatoimp, NULL); 
    if(matriz.Sdir_imp != NULL) pasos->Sdir_imp = ListaOrdenParcial(matriz.Sdir_imp, NULL); 
    if(matriz.Spilaimp != NULL) pasos->Spilaimp = ListaOrdenParcial(matriz.Spilaimp, NULL); 
    if(matriz.Sestadoimp != NULL) pasos->Sestadoimp = ListaOrdenParcial(matriz.Sestadoimp, NULL); 

    if(matriz.D != NULL) pasos->D = ListaOrdenParcial(matriz.D, NULL); 
}



/* esta función calcula el grado de paralelismo a partir de los pasos de computación */
/* ver si es necesario prevenir la división por 0 */

/*
void CalcularGradoParalelismo(parametromatriz *pasos, parametromatriz *grado)
{
    if(matriz.Ddatoexp != NULL) grado->Ddatoexp = 1 / pasos->Ddatoexp;
    if(matriz.Ddir_exp != NULL) grado->Ddir_exp = 1 / pasos->Ddir_exp;
    if(matriz.Dpilaexp != NULL) grado->Dpilaexp = 1 / pasos->Dpilaexp; 
    if(matriz.Destadoexp != NULL) grado->Destadoexp = 1 / pasos->Destadoexp; 
        
    if(matriz.Ddatoimp != NULL) grado->Ddatoimp = 1 / pasos->Ddatoimp; 
    if(matriz.Ddir_imp != NULL) grado->Ddir_imp = 1 / pasos->Ddir_imp; 
    if(matriz.Dpilaimp != NULL) grado->Dpilaimp = 1 / pasos->Dpilaimp; 
    if(matriz.Destadoimp != NULL) grado->Destadoimp = 1 / pasos->Destadoimp; 

    if(matriz.ADdatoexp != NULL) grado->ADdatoexp = 1 / pasos->ADdatoexp; 
    if(matriz.ADdir_exp != NULL) grado->ADdir_exp = 1 / pasos->ADdir_exp; 
    if(matriz.ADpilaexp != NULL) grado->ADpilaexp = 1 / pasos->ADpilaexp; 
    if(matriz.ADestadoexp != NULL) grado->ADestadoexp = 1 / pasos->ADestadoexp; 
        
    if(matriz.ADdatoimp != NULL) grado->ADdatoimp = 1 / pasos->ADdatoimp; 
    if(matriz.ADdir_imp != NULL) grado->ADdir_imp = 1 / pasos->ADdir_imp; 
    if(matriz.ADpilaimp != NULL) grado->ADpilaimp = 1 / pasos->ADpilaimp; 
    if(matriz.ADestadoimp != NULL) grado->ADestadoimp = 1 / pasos->ADestadoimp; 

    if(matriz.Sdatoexp != NULL) grado->Sdatoexp = 1 / pasos->Sdatoexp; 
    if(matriz.Sdir_exp != NULL) grado->Sdir_exp = 1 / pasos->Sdir_exp; 
    if(matriz.Spilaexp != NULL) grado->Spilaexp = 1 / pasos->Spilaexp; 
    if(matriz.Sestadoexp != NULL) grado->Sestadoexp = 1 / pasos->Sestadoexp; 
        
    if(matriz.Sdatoimp != NULL) grado->Sdatoimp = 1 / pasos->Sdatoimp; 
    if(matriz.Sdir_imp != NULL) grado->Sdir_imp = 1 / pasos->Sdir_imp; 
    if(matriz.Spilaimp != NULL) grado->Spilaimp = 1 / pasos->Spilaimp; 
    if(matriz.Sestadoimp != NULL) grado->Sestadoimp = 1 / pasos->Sestadoimp; 

    if(matriz.D != NULL) grado->D = 1 / pasos->D; 
}

*/



/* esta función calcula el grado de paralelismo NORMALIZADO a partir de */
/* la dimensión de la ventana de instrucciones y de los pasos de computación */

void CalcularGradoParalelismoNormalizado(parametromatriz *pasos, parametromatriz *grado)
{
    unsigned int dim;

    dim = configuracion.ventana;
    
    if(matriz.Ddatoexp != NULL) grado->Ddatoexp = InversoNormalizado(dim, pasos->Ddatoexp);
    if(matriz.Ddir_exp != NULL) grado->Ddir_exp = InversoNormalizado(dim, pasos->Ddir_exp);
    if(matriz.Dpilaexp != NULL) grado->Dpilaexp = InversoNormalizado(dim, pasos->Dpilaexp); 
    if(matriz.Destadoexp != NULL) grado->Destadoexp = InversoNormalizado(dim, pasos->Destadoexp); 
        
    if(matriz.Ddatoimp != NULL) grado->Ddatoimp = InversoNormalizado(dim, pasos->Ddatoimp); 
    if(matriz.Ddir_imp != NULL) grado->Ddir_imp = InversoNormalizado(dim, pasos->Ddir_imp); 
    if(matriz.Dpilaimp != NULL) grado->Dpilaimp = InversoNormalizado(dim, pasos->Dpilaimp); 
    if(matriz.Destadoimp != NULL) grado->Destadoimp = InversoNormalizado(dim, pasos->Destadoimp); 

    if(matriz.ADdatoexp != NULL) grado->ADdatoexp = InversoNormalizado(dim, pasos->ADdatoexp); 
    if(matriz.ADdir_exp != NULL) grado->ADdir_exp = InversoNormalizado(dim, pasos->ADdir_exp); 
    if(matriz.ADpilaexp != NULL) grado->ADpilaexp = InversoNormalizado(dim, pasos->ADpilaexp); 
    if(matriz.ADestadoexp != NULL) grado->ADestadoexp = InversoNormalizado(dim, pasos->ADestadoexp); 
        
    if(matriz.ADdatoimp != NULL) grado->ADdatoimp = InversoNormalizado(dim, pasos->ADdatoimp); 
    if(matriz.ADdir_imp != NULL) grado->ADdir_imp = InversoNormalizado(dim, pasos->ADdir_imp); 
    if(matriz.ADpilaimp != NULL) grado->ADpilaimp = InversoNormalizado(dim, pasos->ADpilaimp); 
    if(matriz.ADestadoimp != NULL) grado->ADestadoimp = InversoNormalizado(dim, pasos->ADestadoimp); 

    if(matriz.Sdatoexp != NULL) grado->Sdatoexp = InversoNormalizado(dim, pasos->Sdatoexp); 
    if(matriz.Sdir_exp != NULL) grado->Sdir_exp = InversoNormalizado(dim, pasos->Sdir_exp); 
    if(matriz.Spilaexp != NULL) grado->Spilaexp = InversoNormalizado(dim, pasos->Spilaexp); 
    if(matriz.Sestadoexp != NULL) grado->Sestadoexp = InversoNormalizado(dim, pasos->Sestadoexp); 
        
    if(matriz.Sdatoimp != NULL) grado->Sdatoimp = InversoNormalizado(dim, pasos->Sdatoimp); 
    if(matriz.Sdir_imp != NULL) grado->Sdir_imp = InversoNormalizado(dim, pasos->Sdir_imp); 
    if(matriz.Spilaimp != NULL) grado->Spilaimp = InversoNormalizado(dim, pasos->Spilaimp); 
    if(matriz.Sestadoimp != NULL) grado->Sestadoimp = InversoNormalizado(dim, pasos->Sestadoimp); 

    if(matriz.D != NULL) grado->D = InversoNormalizado(dim, pasos->D); 
}


/* esta función calcula el acoplamiento de cada matriz de dependencias */

void CalcularAcoplamiento(parametromatriz *acoplamiento)
{
    if(matriz.Ddatoexp != NULL) acoplamiento->Ddatoexp = Acoplamiento(matriz.Ddatoexp);
    if(matriz.Ddir_exp != NULL) acoplamiento->Ddir_exp = Acoplamiento(matriz.Ddir_exp);
    if(matriz.Dpilaexp != NULL) acoplamiento->Dpilaexp = Acoplamiento(matriz.Dpilaexp); 
    if(matriz.Destadoexp != NULL) acoplamiento->Destadoexp = Acoplamiento(matriz.Destadoexp); 
        
    if(matriz.Ddatoimp != NULL) acoplamiento->Ddatoimp = Acoplamiento(matriz.Ddatoimp); 
    if(matriz.Ddir_imp != NULL) acoplamiento->Ddir_imp = Acoplamiento(matriz.Ddir_imp); 
    if(matriz.Dpilaimp != NULL) acoplamiento->Dpilaimp = Acoplamiento(matriz.Dpilaimp); 
    if(matriz.Destadoimp != NULL) acoplamiento->Destadoimp = Acoplamiento(matriz.Destadoimp); 

    if(matriz.ADdatoexp != NULL) acoplamiento->ADdatoexp = Acoplamiento(matriz.ADdatoexp); 
    if(matriz.ADdir_exp != NULL) acoplamiento->ADdir_exp = Acoplamiento(matriz.ADdir_exp); 
    if(matriz.ADpilaexp != NULL) acoplamiento->ADpilaexp = Acoplamiento(matriz.ADpilaexp); 
    if(matriz.ADestadoexp != NULL) acoplamiento->ADestadoexp = Acoplamiento(matriz.ADestadoexp); 
        
    if(matriz.ADdatoimp != NULL) acoplamiento->ADdatoimp = Acoplamiento(matriz.ADdatoimp); 
    if(matriz.ADdir_imp != NULL) acoplamiento->ADdir_imp = Acoplamiento(matriz.ADdir_imp); 
    if(matriz.ADpilaimp != NULL) acoplamiento->ADpilaimp = Acoplamiento(matriz.ADpilaimp); 
    if(matriz.ADestadoimp != NULL) acoplamiento->ADestadoimp = Acoplamiento(matriz.ADestadoimp); 

    if(matriz.Sdatoexp != NULL) acoplamiento->Sdatoexp = Acoplamiento(matriz.Sdatoexp); 
    if(matriz.Sdir_exp != NULL) acoplamiento->Sdir_exp = Acoplamiento(matriz.Sdir_exp); 
    if(matriz.Spilaexp != NULL) acoplamiento->Spilaexp = Acoplamiento(matriz.Spilaexp); 
    if(matriz.Sestadoexp != NULL) acoplamiento->Sestadoexp = Acoplamiento(matriz.Sestadoexp); 
        
    if(matriz.Sdatoimp != NULL) acoplamiento->Sdatoimp = Acoplamiento(matriz.Sdatoimp); 
    if(matriz.Sdir_imp != NULL) acoplamiento->Sdir_imp = Acoplamiento(matriz.Sdir_imp); 
    if(matriz.Spilaimp != NULL) acoplamiento->Spilaimp = Acoplamiento(matriz.Spilaimp); 
    if(matriz.Sestadoimp != NULL) acoplamiento->Sestadoimp = Acoplamiento(matriz.Sestadoimp); 

    if(matriz.D != NULL) acoplamiento->D = (double) Acoplamiento(matriz.D); 
}



/* esta función reserva memoria para salvar el histograma de pasos de computación */
/* asociado a la matriz de dependencias de datos D (no el resto) */

void CrearHistogramaPasos()
{
    char mensaje[MAX_LINE];

    distribucionpasos = calloc(configuracion.ventana+1, sizeof(unsigned long));
    if (distribucionpasos == NULL)
    {
        sprintf(mensaje, "[CrearHistogramaPasos] Memoria insuficiente");
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
        /* el programa finaliza si no hay memoria suficiente */
    }
}


/* inicia el histograma a 0 (con la reserva de calloc no es necesario) */

void IniciarHistogramaPasos()
{
    unsigned int i;

    for(i=0; i<configuracion.ventana; i++) distribucionpasos[i] = 0;
}


/* libera la memoria reservada para el histograma */

void LiberarMemoriaHistogramaPasos()
{
    free(distribucionpasos);
}


/* actualiza los datos del histograma */

void ActualizarHistogramaPasos()
{
    distribucionpasos[(unsigned int)pasos->D]++;
}


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>