Annotation of ADD_ver_10/CalculosMatrices.c, revision 1.2

1.1       rico        1: /******************************************************************************/
                      2: /* MÓDULO: CalculosMatrices.c                                                 */
                      3: /*                                                                            */
                      4: /* Este módulo contiene las funciones que realizan cálculos sobre             */
                      5: /* las matrices.                                                              */
                      6: /******************************************************************************/
                      7: /* Fecha: 26 de septiembre de 2005                                            */
                      8: /******************************************************************************/
                      9: 
                     10: #include <stdio.h>
                     11: #include <stdlib.h>
                     12: #include <string.h>
                     13: 
                     14: #include "defines.h"
                     15: #include "tipos.h"
                     16: #include "calculosmatrices.h"
                     17: 
                     18: /* configuración */
                     19: extern struct argumentos configuracion;
                     20: 
                     21: /* análisis de dependencias de datos */
                     22: extern struct punterosD matriz;
                     23: extern unsigned char **matrizC;
                     24: extern char **OrdenParcial;
                     25: 
                     26: /* parámetros asociados a las matrices */
                     27: extern parametromatriz *pasos;
                     28: extern parametromatriz *mediapasos;
                     29: extern parametromatriz *grado;
                     30: extern parametromatriz *mediagrado;
                     31: extern parametromatriz *acoplo;
                     32: extern parametromatriz *mediaacoplo;
                     33: 
                     34: /* otros resultados */
                     35: extern unsigned long *distribucionpasos;
                     36: 
                     37: 
                     38: /* esta función calcula la matriz de caminos de dependencias C */
                     39: /* a partir de una matriz de dependencias D */
                     40: /* devuelve el número de pasos de computación requeridos para */
                     41: /* finalizar la computación de la secuencia expresada por D */
                     42: /* (la matriz de caminos devuelta no ha sido reducida a 0s y 1s) */
                     43: 
                     44: /* esta función es muy consumidora de tiempo ya que calcula potencias de D */
                     45: 
                     46: unsigned int CalcularMatrizCaminos(unsigned char **D, unsigned char **C)
                     47: {
1.2     ! rico       48:     char mensaje[MAX_LINE];
        !            49:     unsigned char *v;        /* vector temporal */
        !            50:     unsigned char **tmp;    /* matriz temporal */
        !            51: 
        !            52:     unsigned int i, j, k, potencia;
        !            53:     unsigned int suma;
        !            54:     unsigned char matriz_nula;
        !            55: 
        !            56: 
        !            57:     if(D == NULL)
        !            58:     {
        !            59:         sprintf(mensaje, "[CalcularMatrizCaminos] La matriz D indicada no existe");
        !            60:         Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !            61:     }
        !            62: 
        !            63:     /* necesito un vector y una matriz temporal de 'unsigned char' */
        !            64:     /* para calcular las sucesivas potencias de la matriz D */
1.1       rico       65: 
1.2     ! rico       66:     /* hago la reserva de memoria para el vector */
        !            67:     v = calloc(configuracion.ventana , sizeof(unsigned char *));
        !            68:     if (v == NULL)
        !            69:     {
        !            70:         sprintf(mensaje, "[CalcularMatrizCaminos] Memoria insuficiente");
        !            71:         Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !            72:         /* el programa finaliza si no hay memoria suficiente */
        !            73:     }
        !            74: 
        !            75:     /* hago la reserva de memoria para la matriz */
        !            76:     /* 1º un puntero por cada fila */
        !            77:     tmp = calloc(configuracion.ventana , sizeof(unsigned char *));
        !            78:     if (tmp == NULL)
        !            79:     {
        !            80:         sprintf(mensaje, "[CalcularMatrizCaminos] Memoria insuficiente");
        !            81:         Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !            82:         /* el programa finaliza si no hay memoria suficiente */
        !            83:     }
        !            84:     /* 2º un 'char' por cada columna */
        !            85:     for(i=0; i<configuracion.ventana; i++)
        !            86:     {
        !            87:         tmp[i] = calloc(configuracion.ventana, sizeof(unsigned char));
        !            88:         if (tmp[i] == NULL)
        !            89:         {
        !            90:             sprintf(mensaje, "[CalcularMatrizCaminos] Memoria insuficiente");
        !            91:             Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !            92:             /* el programa finaliza si no hay memoria suficiente */
        !            93:         }
        !            94:     }
        !            95: 
        !            96: 
        !            97:     /* inicio la matriz temporal con la matriz 'identidad' (1s en la diagonal) */
        !            98:     /* al reservar con 'calloc' se rellena con 0s */
        !            99: 
        !           100:     for(i=0; i<configuracion.ventana; i++) tmp[i][i] = 1;
        !           101: 
        !           102: 
        !           103:     /* calculo sucesivas potencias de la matriz 'D' hasta que se anule */
        !           104:     /* utilizo la expresión TMP * D = TMP */
        !           105:     /* el uso del vector me permite escribir el resultado sobre 'TMP' */
        !           106:     for(potencia=0; potencia<configuracion.ventana; potencia++)
        !           107:     {
        !           108:         for(i=0; i<configuracion.ventana; i++)
        !           109:         {
        !           110:               for(k=0; k<configuracion.ventana; k++) v[k]=tmp[i][k];
        !           111:             for(j=0; j<configuracion.ventana; j++)
        !           112:             {
        !           113:                 suma = 0;
        !           114:                 for(k=0; k<configuracion.ventana; k++)
        !           115:                 {
        !           116:                     suma += v[k] * D[k][j];
        !           117:                 }
        !           118:                 tmp[i][j] = suma;
        !           119:             }
        !           120:         }
        !           121: 
        !           122:         /* la matriz 'TMP' contiene la n-ésima+1 potencia de 'D' */
        !           123: 
        !           124:         /* ahora evalúo si el resultado es la matriz nula */
        !           125:         /* si es así no tengo que continuar ya que no hay */
        !           126:         /* caminos de dependencias de longitud mayor */
        !           127: 
        !           128:         matriz_nula = SI;
        !           129:         for(i=0; i<configuracion.ventana; i++)
        !           130:         {
        !           131:             for(j=0; j<configuracion.ventana; j++)
        !           132:             {
        !           133:                 if(tmp[i][j] != 0) {matriz_nula = NO; break;}
        !           134:             }
        !           135:             if(matriz_nula == NO) break;
        !           136:         }
        !           137:         if(matriz_nula == SI) break;
        !           138: 
        !           139:         /* sumo la nueva potencia de la matriz de dependencias D^^p */
        !           140:         /* a la matriz de caminos parcial 'C' si me han pasado un puntero no nulo */
        !           141:         if(*C != NULL)
        !           142:         {
        !           143:             for(i=0; i<configuracion.ventana; i++)
        !           144:             {
        !           145:                 for(j=0; j<configuracion.ventana; j++) C[i][j] += tmp[i][j];
        !           146:             }
        !           147:         }
        !           148:     }
        !           149: 
        !           150:     /* libero la memoria reservada anteriormente */
        !           151:     /* libero el vector */
        !           152:     free(v);
        !           153:     /* libero la matriz */
        !           154:     for(i=0; i<configuracion.ventana; i++) free(tmp[i]); free(tmp);
        !           155: 
        !           156:     return potencia+1;    /* devuelve el rango de la primera potencia nula de 'D' */
1.1       rico      157: }
                    158: 
                    159: 
                    160: /* esta función establece la lista del orden parcial contenido en D */
                    161: /* y devuelve el número de pasos de computación del camino crítico */
                    162: /* si le pasamos un puntero NULO en el parámetro lista sólo realiza el */
                    163: /* calculo de pasos de computación (método más rápido que el anterior) */
                    164: /* se asume que la matriz D no ha sido reducida a 0s y 1s */
                    165: 
                    166: unsigned int ListaOrdenParcial(unsigned char **D, char **lista)
                    167: {
1.2     ! rico      168:     char mensaje[MAX_LINE];
        !           169:     unsigned char *lanzadas;    /* vector de instrucciones lanzadas */
        !           170:     unsigned char **tmp;        /* matriz temporal */
1.1       rico      171: 
                    172:     unsigned int pasos, procesadas;
                    173:     unsigned int i, j;
1.2     ! rico      174:     char cadena[6];        /* cadena para pasar enteros a strings */
1.1       rico      175: 
                    176: 
1.2     ! rico      177:     if(D == NULL)
        !           178:     {
        !           179:         sprintf(mensaje, "[ListaOrdenParcial] La matriz D indicada no existe");
        !           180:         Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !           181:     }
1.1       rico      182: 
1.2     ! rico      183:     /* necesito un vector y una matriz temporal de 'unsigned char' */
        !           184:     /* para calcular las sucesivas potencias de la matriz D */
        !           185: 
        !           186:     /* hago la reserva de memoria para el vector */
        !           187:     lanzadas = calloc(configuracion.ventana , sizeof(unsigned char *));
        !           188:     if (lanzadas == NULL)
        !           189:     {
        !           190:         sprintf(mensaje, "[ListaOrdenParcial] Memoria insuficiente");
        !           191:         Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !           192:         /* el programa finaliza si no hay memoria suficiente */
        !           193:     }
1.1       rico      194: 
1.2     ! rico      195:     /* hago la reserva de memoria para la matriz */
        !           196:     /* 1º un puntero por cada fila */
        !           197:     tmp = calloc(configuracion.ventana , sizeof(unsigned char *));
        !           198:     if (tmp == NULL)
        !           199:     {
        !           200:         sprintf(mensaje, "[ListaOrdenParcial] Memoria insuficiente");
        !           201:         Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !           202:         /* el programa finaliza si no hay memoria suficiente */
        !           203:     }
        !           204:     /* 2º un 'char' por cada columna */
        !           205:     for(i=0; i<configuracion.ventana; i++)
        !           206:     {
        !           207:         tmp[i] = calloc(configuracion.ventana, sizeof(unsigned char));
        !           208:         if (tmp[i] == NULL)
        !           209:         {
        !           210:             sprintf(mensaje, "[ListaOrdenParcial] Memoria insuficiente");
        !           211:             Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !           212:             /* el programa finaliza si no hay memoria suficiente */
        !           213:         }
        !           214:     }
        !           215: 
        !           216:     /* copio la matriz de dependencias D sobre la temporal */
        !           217:     for(i=0; i<configuracion.ventana; i++)
        !           218:     {
        !           219:         for(j=0; j<configuracion.ventana; j++) tmp[i][j] = D[i][j];
        !           220:     }
        !           221:     
        !           222:     /* pongo a cero el vector de lanzadas */
        !           223:     for(i=0; i<configuracion.ventana; i++) lanzadas[i] = 0;
        !           224: 
        !           225:     /* inicio el contador de pasos de computaci¢n */
        !           226:     pasos = 0;
        !           227: 
        !           228:     /* inicio el contador de instrucciones procesadas */
1.1       rico      229:     procesadas = 0;
                    230: 
                    231: 
1.2     ! rico      232:     while(configuracion.ventana - procesadas)
        !           233:     {
        !           234:         pasos++;
1.1       rico      235: 
1.2     ! rico      236:         /* busco tareas independientes entre las NO lanzadas */
        !           237:         for(i=0; i<configuracion.ventana; i++)
        !           238:         {
        !           239:             if(lanzadas[i]==0)    /* si es 0 significa que no se ha lanzado */
        !           240:             {
        !           241:                    /* miro si el vector de dependencias es nulo */
        !           242:                 for(j=0; j<i; j++)
        !           243:                 {
        !           244:                     if(tmp[i][j]!=0) break;
        !           245:                 }
        !           246:                 if(j==i)
        !           247:                 {
        !           248:                     lanzadas[i]=1; /* la instrucci¢n es independiente */
        !           249: 
        !           250:                     /* anoto la instrucción en la lista del orden parcial */
        !           251:                     /* en el paso de computación en curso */
        !           252:                     if(lista != NULL)
        !           253:                     {
        !           254:                         sprintf(cadena, "%u", i);
        !           255:                         AgregarElementoLista(lista[pasos-1], cadena);
        !           256:                     }
        !           257:                 }
        !           258:             }
        !           259:         }
        !           260: 
        !           261:         /* ahora actualizo la matriz de dependencias con la lista de */
        !           262:         /* instrucciones independientes que han sido lanzadas */
        !           263: 
        !           264:         for(i=0; i<configuracion.ventana; i++)
        !           265:         {
        !           266:             if(lanzadas[i]==1)    /* si es 1 significa que es independiente */
        !           267:             {
        !           268:                 for(j=i+1; j<configuracion.ventana; j++)
        !           269:                 {
        !           270:                     if(tmp[j][i]!=0) tmp[j][i]=0;
        !           271:                 }
        !           272:             }
        !           273:         }
        !           274: 
        !           275:         /* ahora actualizo el vector de lanzadas */
        !           276:         for(i=0; i<configuracion.ventana; i++)
        !           277:         {
        !           278:             if(lanzadas[i]==1)
        !           279:             {
        !           280:                 lanzadas[i]=2; /* significa que ha sido procesada */
        !           281:                    procesadas++;
        !           282:             }
        !           283:         }
        !           284:     }
        !           285: 
        !           286:     /* libero la memoria reservada anteriormente */
        !           287:     /* libero el vector */
        !           288:     free(lanzadas);
        !           289:     /* libero la matriz */
        !           290:     for(i=0; i<configuracion.ventana; i++) free(tmp[i]); free(tmp);
        !           291: 
        !           292:     return pasos;
1.1       rico      293: }
                    294: 
                    295: 
                    296: /* esta función determina el 'acoplamiento' de una matriz de dependencias de datos */
                    297: 
                    298: unsigned int Acoplamiento(unsigned char **D)
                    299: {
1.2     ! rico      300:     char mensaje[MAX_LINE];
        !           301:     unsigned int i, j;
        !           302:     unsigned int acoplo = 0;
1.1       rico      303: 
1.2     ! rico      304:     if(D == NULL)
        !           305:     {
        !           306:         sprintf(mensaje, "[Acoplamiento] La matriz D indicada no existe");
        !           307:         Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !           308:     }
        !           309: 
        !           310:     /* puesto que las matrices se obtienen de la secuencia de código */
        !           311:     /* estamos seguros de que son canónicas y, por tanto, no es necesario */
        !           312:     /* hacer el recorrido completo de todas sus componentes */
        !           313:     /* basta con empezar en la instrucción 1 y recorres columnas hasta la diagonal */
        !           314:     for(i=1; i<configuracion.ventana; i++)
        !           315:     {
        !           316:         for(j=0; j<i; j++) if(D[i][j] != 0) acoplo++;
        !           317:     }
        !           318: 
        !           319:     return acoplo;
1.1       rico      320: }
                    321: 
                    322: 
                    323: 
                    324: /* esta función reserva memoria para un array de 'num_cadenas' de punteros /*
                    325: /* a cadenas de caracteres de tamaño fijo 'tamano' y devuelve el puntero */
                    326: 
                    327: /* con esta estructura implantaremos la lista de orden parcial */
                    328: /* trabajando con punteros a char y cadenas de tamaño variable puede */
                    329: /* ser más eficaz pero es necesario ser más cuidadoso */
                    330: 
                    331: char ** CrearArrayStrings(unsigned int num_cadenas, unsigned int tamano)
                    332: {
1.2     ! rico      333:     char mensaje[MAX_LINE];
        !           334:     unsigned int i;
        !           335:     char **listado;
        !           336: 
        !           337:     /* 1º un puntero por cada fila */
        !           338:     listado = calloc(num_cadenas, sizeof(char *));
        !           339:     if (listado == NULL)
        !           340:     {
        !           341:         sprintf(mensaje, "[CrearArrayStrings] Memoria insuficiente");
        !           342:         Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !           343:         /* el programa finaliza si no hay memoria suficiente */
        !           344:     }
        !           345:     /* 2º cuatro 'char' por cada columna (3 caracteres de número y un separador ':') */
        !           346:     for(i=0; i<configuracion.ventana; i++)
        !           347:     {
        !           348:         listado[i] = calloc(tamano, sizeof(char));
        !           349:         if (listado[i] == NULL)
        !           350:         {
        !           351:             sprintf(mensaje, "[CrearArrayStrings] Memoria insuficiente");
        !           352:             Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !           353:             /* el programa finaliza si no hay memoria suficiente */
        !           354:         }
        !           355:     }
        !           356:     return listado;
1.1       rico      357: }
                    358: 
                    359: 
                    360: /* reserva memoria para construir un listado de orden parcial: */
                    361: /* cada línea del listado corresponde a un paso de computación */
                    362: /* y cada paso de computación contiene una cadena con la lista */
                    363: /* de instrucciones sin dependencias de datos en ese momento */
                    364: 
                    365: void CrearListaOrdenParcial()
                    366: {
1.2     ! rico      367:     unsigned int dim;
1.1       rico      368: 
1.2     ! rico      369:     dim = configuracion.ventana;
1.1       rico      370: 
1.2     ! rico      371:     OrdenParcial = CrearArrayStrings(dim, 4*dim);
1.1       rico      372: }
                    373: 
                    374: 
                    375: /* inicia el listado de orden parcial rellenando con la cadena vacía '\0' */
                    376: 
                    377: void IniciarListaOrdenParcial()
                    378: {
1.2     ! rico      379:     unsigned int i, dim;
1.1       rico      380: 
1.2     ! rico      381:     dim = configuracion.ventana;
        !           382:     
        !           383:     if(OrdenParcial != NULL) for(i=0; i<dim; i++) *OrdenParcial[i] = '\0'; 
1.1       rico      384: }
                    385: 
                    386: 
                    387: /* libera la memoria reservada para el listado de orden parcial */
                    388: 
                    389: void LiberarMemoriaListaOrdenParcial()
                    390: {
1.2     ! rico      391:     unsigned int i,dim;
1.1       rico      392: 
1.2     ! rico      393:     dim = configuracion.ventana;
1.1       rico      394: 
1.2     ! rico      395:     if(OrdenParcial != NULL)
        !           396:     {
        !           397:         for(i=0; i<dim; i++)
        !           398:         {
        !           399:             free(OrdenParcial[i]); 
        !           400:         }
        !           401:         free(OrdenParcial);
        !           402:     }
1.1       rico      403: }
                    404: 
                    405: 
                    406: /* crea la matriz de caminos de dependencias */
                    407: 
                    408: void CrearMatrizCaminos()
                    409: {
1.2     ! rico      410:     matrizC = CrearMatriz();
1.1       rico      411: }
                    412: 
                    413: 
                    414: /* inicia la matriz de caminos de dependencias */
                    415: 
                    416: void IniciarMatrizCaminos()
                    417: {
1.2     ! rico      418:     IniciarMatriz(matrizC);
1.1       rico      419: }
                    420: 
                    421: 
                    422: /* libera la memoria de la matriz de caminos */
                    423: 
                    424: void LiberarMemoriaMatrizCaminos()
                    425: {
1.2     ! rico      426:     LiberarMemoriaMatriz(matrizC);
1.1       rico      427: }
                    428: 
                    429: 
                    430: /* reserva espacio en memoria para una variable agregada */
                    431: 
                    432: parametromatriz * CrearVariableAgregada()
                    433: {
1.2     ! rico      434:     char mensaje[MAX_LINE];
        !           435:     parametromatriz *variable;
        !           436:     
        !           437:     variable = calloc(1, sizeof(parametromatriz));
        !           438:     if (variable == NULL)
        !           439:     {
        !           440:         sprintf(mensaje, "[CrearVariableAgragada] Memoria insuficiente");
        !           441:         Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !           442:         /* el programa finaliza si no hay memoria suficiente */
        !           443:     }
1.1       rico      444: 
1.2     ! rico      445:     return variable;
1.1       rico      446: }
                    447: 
                    448: 
                    449: /* inicia a 0 una variable agregada */
                    450: 
                    451: void IniciarVariableAgregada(parametromatriz *variable)
                    452: {
1.2     ! rico      453:     variable->Ddatoexp = 0.0;
        !           454:     variable->Ddir_exp = 0.0;
        !           455:     variable->Dpilaexp = 0.0; 
        !           456:     variable->Destadoexp = 0.0; 
        !           457:         
        !           458:     variable->Ddatoimp = 0.0; 
        !           459:     variable->Ddir_imp = 0.0; 
        !           460:     variable->Dpilaimp = 0.0; 
        !           461:     variable->Destadoimp = 0.0; 
        !           462: 
        !           463:     variable->ADdatoexp = 0.0; 
        !           464:     variable->ADdir_exp = 0.0; 
        !           465:     variable->ADpilaexp = 0.0; 
        !           466:     variable->ADestadoexp = 0.0; 
        !           467:         
        !           468:     variable->ADdatoimp = 0.0; 
        !           469:     variable->ADdir_imp = 0.0; 
        !           470:     variable->ADpilaimp = 0.0; 
        !           471:     variable->ADestadoimp = 0.0; 
        !           472: 
        !           473:     variable->Sdatoexp = 0.0; 
        !           474:     variable->Sdir_exp = 0.0; 
        !           475:     variable->Spilaexp = 0.0; 
        !           476:     variable->Sestadoexp = 0.0; 
        !           477:         
        !           478:     variable->Sdatoimp = 0.0; 
        !           479:     variable->Sdir_imp = 0.0; 
        !           480:     variable->Spilaimp = 0.0; 
        !           481:     variable->Sestadoimp = 0.0; 
1.1       rico      482: 
1.2     ! rico      483:     variable->D = 0.0; 
1.1       rico      484: }
                    485: 
                    486: 
                    487: 
                    488: /* esta función calcula el nuevo promedio de una variable agregada (media) a partir del */
                    489: /* índice (n) y del valor actual o en curso de esa variable (actual) */
                    490: 
                    491: /*
                    492: void CalcularPromedioVariableAgregada(parametromatriz *media, parametromatriz *actual, unsigned long n)
                    493: {
1.2     ! rico      494:     if(matriz.Ddatoexp != NULL) media->Ddatoexp = ((n - 1) * media->Ddatoexp + actual->Ddatoexp) / n;
        !           495:     if(matriz.Ddir_exp != NULL) media->Ddir_exp = ((n - 1) * media->Ddir_exp + actual->Ddir_exp) / n;
        !           496:     if(matriz.Dpilaexp != NULL) media->Dpilaexp = ((n - 1) * media->Dpilaexp + actual->Dpilaexp) / n; 
        !           497:     if(matriz.Destadoexp != NULL) media->Destadoexp = ((n - 1) * media->Destadoexp + actual->Destadoexp) / n; 
        !           498:         
        !           499:     if(matriz.Ddatoimp != NULL) media->Ddatoimp = ((n - 1) * media->Ddatoimp + actual->Ddatoimp) / n; 
        !           500:     if(matriz.Ddir_imp != NULL) media->Ddir_imp = ((n - 1) * media->Ddir_imp + actual->Ddir_imp) / n; 
        !           501:     if(matriz.Dpilaimp != NULL) media->Dpilaimp = ((n - 1) * media->Dpilaimp + actual->Dpilaimp) / n; 
        !           502:     if(matriz.Destadoimp != NULL) media->Destadoimp = ((n - 1) * media->Destadoimp + actual->Destadoimp) / n; 
        !           503: 
        !           504:     if(matriz.ADdatoexp != NULL) media->ADdatoexp = ((n - 1) * media->ADdatoexp + actual->ADdatoexp) / n; 
        !           505:     if(matriz.ADdir_exp != NULL) media->ADdir_exp = ((n - 1) * media->ADdir_exp + actual->ADdir_exp) / n; 
        !           506:     if(matriz.ADpilaexp != NULL) media->ADpilaexp = ((n - 1) * media->ADpilaexp + actual->ADpilaexp) / n; 
        !           507:     if(matriz.ADestadoexp != NULL) media->ADestadoexp = ((n - 1) * media->ADestadoexp + actual->ADestadoexp) / n; 
        !           508:         
        !           509:     if(matriz.ADdatoimp != NULL) media->ADdatoimp = ((n - 1) * media->ADdatoimp + actual->ADdatoimp) / n; 
        !           510:     if(matriz.ADdir_imp != NULL) media->ADdir_imp = ((n - 1) * media->ADdir_imp + actual->ADdir_imp) / n; 
        !           511:     if(matriz.ADpilaimp != NULL) media->ADpilaimp = ((n - 1) * media->ADpilaimp + actual->ADpilaimp) / n; 
        !           512:     if(matriz.ADestadoimp != NULL) media->ADestadoimp = ((n - 1) * media->ADestadoimp + actual->ADestadoimp) / n; 
        !           513: 
        !           514:     if(matriz.Sdatoexp != NULL) media->Sdatoexp = ((n - 1) * media->Sdatoexp + actual->Sdatoexp) / n; 
        !           515:     if(matriz.Sdir_exp != NULL) media->Sdir_exp = ((n - 1) * media->Sdir_exp + actual->Sdir_exp) / n; 
        !           516:     if(matriz.Spilaexp != NULL) media->Spilaexp = ((n - 1) * media->Spilaexp + actual->Spilaexp) / n; 
        !           517:     if(matriz.Sestadoexp != NULL) media->Sestadoexp = ((n - 1) * media->Sestadoexp + actual->Sestadoexp) / n; 
        !           518:         
        !           519:     if(matriz.Sdatoimp != NULL) media->Sdatoimp = ((n - 1) * media->Sdatoimp + actual->Sdatoimp) / n; 
        !           520:     if(matriz.Sdir_imp != NULL) media->Sdir_imp = ((n - 1) * media->Sdir_imp + actual->Sdir_imp) / n; 
        !           521:     if(matriz.Spilaimp != NULL) media->Spilaimp = ((n - 1) * media->Spilaimp + actual->Spilaimp) / n; 
        !           522:     if(matriz.Sestadoimp != NULL) media->Sestadoimp = ((n - 1) * media->Sestadoimp + actual->Sestadoimp) / n; 
1.1       rico      523: 
1.2     ! rico      524:     if(matriz.D != NULL) media->D = ((n - 1) * media->D + actual->D) / n; 
1.1       rico      525: }
                    526: */
                    527: 
                    528: 
                    529: /* utilizando la función: */
                    530: /* double CalcularNuevoPromedio (double promedioanterior, double valoractual, unsigned long n)
                    531: /* es más compacto aunque quizá algo más lento */
                    532: 
                    533: void CalcularPromedioVariableAgregada(parametromatriz *media, parametromatriz *actual, unsigned long n)
                    534: {
1.2     ! rico      535:     if(matriz.Ddatoexp != NULL) media->Ddatoexp = CalcularNuevoPromedio(media->Ddatoexp, actual->Ddatoexp, n);
        !           536:     if(matriz.Ddir_exp != NULL) media->Ddir_exp = CalcularNuevoPromedio(media->Ddir_exp, actual->Ddir_exp, n);
        !           537:     if(matriz.Dpilaexp != NULL) media->Dpilaexp = CalcularNuevoPromedio(media->Dpilaexp, actual->Dpilaexp, n); 
        !           538:     if(matriz.Destadoexp != NULL) media->Destadoexp = CalcularNuevoPromedio(media->Destadoexp, actual->Destadoexp, n); 
        !           539:         
        !           540:     if(matriz.Ddatoimp != NULL) media->Ddatoimp = CalcularNuevoPromedio(media->Ddatoimp, actual->Ddatoimp, n); 
        !           541:     if(matriz.Ddir_imp != NULL) media->Ddir_imp = CalcularNuevoPromedio(media->Ddir_imp, actual->Ddir_imp, n); 
        !           542:     if(matriz.Dpilaimp != NULL) media->Dpilaimp = CalcularNuevoPromedio(media->Dpilaimp, actual->Dpilaimp, n); 
        !           543:     if(matriz.Destadoimp != NULL) media->Destadoimp = CalcularNuevoPromedio(media->Destadoimp, actual->Destadoimp, n); 
        !           544: 
        !           545:     if(matriz.ADdatoexp != NULL) media->ADdatoexp = CalcularNuevoPromedio(media->ADdatoexp, actual->ADdatoexp, n); 
        !           546:     if(matriz.ADdir_exp != NULL) media->ADdir_exp = CalcularNuevoPromedio(media->ADdir_exp, actual->ADdir_exp, n); 
        !           547:     if(matriz.ADpilaexp != NULL) media->ADpilaexp = CalcularNuevoPromedio(media->ADpilaexp, actual->ADpilaexp, n); 
        !           548:     if(matriz.ADestadoexp != NULL) media->ADestadoexp = CalcularNuevoPromedio(media->ADestadoexp, actual->ADestadoexp, n); 
        !           549:         
        !           550:     if(matriz.ADdatoimp != NULL) media->ADdatoimp = CalcularNuevoPromedio(media->ADdatoimp, actual->ADdatoimp, n); 
        !           551:     if(matriz.ADdir_imp != NULL) media->ADdir_imp = CalcularNuevoPromedio(media->ADdir_imp, actual->ADdir_imp, n); 
        !           552:     if(matriz.ADpilaimp != NULL) media->ADpilaimp = CalcularNuevoPromedio(media->ADpilaimp, actual->ADpilaimp, n); 
        !           553:     if(matriz.ADestadoimp != NULL) media->ADestadoimp = CalcularNuevoPromedio(media->ADestadoimp, actual->ADestadoimp, n); 
        !           554: 
        !           555:     if(matriz.Sdatoexp != NULL) media->Sdatoexp = CalcularNuevoPromedio(media->Sdatoexp, actual->Sdatoexp, n); 
        !           556:     if(matriz.Sdir_exp != NULL) media->Sdir_exp = CalcularNuevoPromedio(media->Sdir_exp, actual->Sdir_exp, n); 
        !           557:     if(matriz.Spilaexp != NULL) media->Spilaexp = CalcularNuevoPromedio(media->Spilaexp, actual->Spilaexp, n); 
        !           558:     if(matriz.Sestadoexp != NULL) media->Sestadoexp = CalcularNuevoPromedio(media->Sestadoexp, actual->Sestadoexp, n); 
        !           559:         
        !           560:     if(matriz.Sdatoimp != NULL) media->Sdatoimp = CalcularNuevoPromedio(media->Sdatoimp, actual->Sdatoimp, n); 
        !           561:     if(matriz.Sdir_imp != NULL) media->Sdir_imp = CalcularNuevoPromedio(media->Sdir_imp, actual->Sdir_imp, n); 
        !           562:     if(matriz.Spilaimp != NULL) media->Spilaimp = CalcularNuevoPromedio(media->Spilaimp, actual->Spilaimp, n); 
        !           563:     if(matriz.Sestadoimp != NULL) media->Sestadoimp = CalcularNuevoPromedio(media->Sestadoimp, actual->Sestadoimp, n); 
1.1       rico      564: 
1.2     ! rico      565:     if(matriz.D != NULL) media->D = CalcularNuevoPromedio(media->D, actual->D, n); 
1.1       rico      566: }
                    567: 
                    568: 
                    569: /* esta función calcula los pasos de computación de cada matriz de dependencias */
                    570: 
                    571: /* para calcular los pasos de computación se usa el método más rápido, es decir, */
                    572: /* construir la lista de orden parcial... aunque no se anote ya que pasamos un puntero nulo */
                    573: 
                    574: void CalcularPasosComputacion(parametromatriz *pasos)
                    575: {
1.2     ! rico      576:     if(matriz.Ddatoexp != NULL) pasos->Ddatoexp = ListaOrdenParcial(matriz.Ddatoexp, NULL);
        !           577:     if(matriz.Ddir_exp != NULL) pasos->Ddir_exp = ListaOrdenParcial(matriz.Ddir_exp, NULL);
        !           578:     if(matriz.Dpilaexp != NULL) pasos->Dpilaexp = ListaOrdenParcial(matriz.Dpilaexp, NULL); 
        !           579:     if(matriz.Destadoexp != NULL) pasos->Destadoexp = ListaOrdenParcial(matriz.Destadoexp, NULL); 
        !           580:         
        !           581:     if(matriz.Ddatoimp != NULL) pasos->Ddatoimp = ListaOrdenParcial(matriz.Ddatoimp, NULL); 
        !           582:     if(matriz.Ddir_imp != NULL) pasos->Ddir_imp = ListaOrdenParcial(matriz.Ddir_imp, NULL); 
        !           583:     if(matriz.Dpilaimp != NULL) pasos->Dpilaimp = ListaOrdenParcial(matriz.Dpilaimp, NULL); 
        !           584:     if(matriz.Destadoimp != NULL) pasos->Destadoimp = ListaOrdenParcial(matriz.Destadoimp, NULL); 
        !           585: 
        !           586:     if(matriz.ADdatoexp != NULL) pasos->ADdatoexp = ListaOrdenParcial(matriz.ADdatoexp, NULL); 
        !           587:     if(matriz.ADdir_exp != NULL) pasos->ADdir_exp = ListaOrdenParcial(matriz.ADdir_exp, NULL); 
        !           588:     if(matriz.ADpilaexp != NULL) pasos->ADpilaexp = ListaOrdenParcial(matriz.ADpilaexp, NULL); 
        !           589:     if(matriz.ADestadoexp != NULL) pasos->ADestadoexp = ListaOrdenParcial(matriz.ADestadoexp, NULL); 
        !           590:         
        !           591:     if(matriz.ADdatoimp != NULL) pasos->ADdatoimp = ListaOrdenParcial(matriz.ADdatoimp, NULL); 
        !           592:     if(matriz.ADdir_imp != NULL) pasos->ADdir_imp = ListaOrdenParcial(matriz.ADdir_imp, NULL); 
        !           593:     if(matriz.ADpilaimp != NULL) pasos->ADpilaimp = ListaOrdenParcial(matriz.ADpilaimp, NULL); 
        !           594:     if(matriz.ADestadoimp != NULL) pasos->ADestadoimp = ListaOrdenParcial(matriz.ADestadoimp, NULL); 
        !           595: 
        !           596:     if(matriz.Sdatoexp != NULL) pasos->Sdatoexp = ListaOrdenParcial(matriz.Sdatoexp, NULL); 
        !           597:     if(matriz.Sdir_exp != NULL) pasos->Sdir_exp = ListaOrdenParcial(matriz.Sdir_exp, NULL); 
        !           598:     if(matriz.Spilaexp != NULL) pasos->Spilaexp = ListaOrdenParcial(matriz.Spilaexp, NULL); 
        !           599:     if(matriz.Sestadoexp != NULL) pasos->Sestadoexp = ListaOrdenParcial(matriz.Sestadoexp, NULL); 
        !           600:         
        !           601:     if(matriz.Sdatoimp != NULL) pasos->Sdatoimp = ListaOrdenParcial(matriz.Sdatoimp, NULL); 
        !           602:     if(matriz.Sdir_imp != NULL) pasos->Sdir_imp = ListaOrdenParcial(matriz.Sdir_imp, NULL); 
        !           603:     if(matriz.Spilaimp != NULL) pasos->Spilaimp = ListaOrdenParcial(matriz.Spilaimp, NULL); 
        !           604:     if(matriz.Sestadoimp != NULL) pasos->Sestadoimp = ListaOrdenParcial(matriz.Sestadoimp, NULL); 
1.1       rico      605: 
1.2     ! rico      606:     if(matriz.D != NULL) pasos->D = ListaOrdenParcial(matriz.D, NULL); 
1.1       rico      607: }
                    608: 
                    609: 
                    610: 
                    611: /* esta función calcula el grado de paralelismo a partir de los pasos de computación */
                    612: /* ver si es necesario prevenir la división por 0 */
                    613: 
                    614: /*
                    615: void CalcularGradoParalelismo(parametromatriz *pasos, parametromatriz *grado)
                    616: {
1.2     ! rico      617:     if(matriz.Ddatoexp != NULL) grado->Ddatoexp = 1 / pasos->Ddatoexp;
        !           618:     if(matriz.Ddir_exp != NULL) grado->Ddir_exp = 1 / pasos->Ddir_exp;
        !           619:     if(matriz.Dpilaexp != NULL) grado->Dpilaexp = 1 / pasos->Dpilaexp; 
        !           620:     if(matriz.Destadoexp != NULL) grado->Destadoexp = 1 / pasos->Destadoexp; 
        !           621:         
        !           622:     if(matriz.Ddatoimp != NULL) grado->Ddatoimp = 1 / pasos->Ddatoimp; 
        !           623:     if(matriz.Ddir_imp != NULL) grado->Ddir_imp = 1 / pasos->Ddir_imp; 
        !           624:     if(matriz.Dpilaimp != NULL) grado->Dpilaimp = 1 / pasos->Dpilaimp; 
        !           625:     if(matriz.Destadoimp != NULL) grado->Destadoimp = 1 / pasos->Destadoimp; 
        !           626: 
        !           627:     if(matriz.ADdatoexp != NULL) grado->ADdatoexp = 1 / pasos->ADdatoexp; 
        !           628:     if(matriz.ADdir_exp != NULL) grado->ADdir_exp = 1 / pasos->ADdir_exp; 
        !           629:     if(matriz.ADpilaexp != NULL) grado->ADpilaexp = 1 / pasos->ADpilaexp; 
        !           630:     if(matriz.ADestadoexp != NULL) grado->ADestadoexp = 1 / pasos->ADestadoexp; 
        !           631:         
        !           632:     if(matriz.ADdatoimp != NULL) grado->ADdatoimp = 1 / pasos->ADdatoimp; 
        !           633:     if(matriz.ADdir_imp != NULL) grado->ADdir_imp = 1 / pasos->ADdir_imp; 
        !           634:     if(matriz.ADpilaimp != NULL) grado->ADpilaimp = 1 / pasos->ADpilaimp; 
        !           635:     if(matriz.ADestadoimp != NULL) grado->ADestadoimp = 1 / pasos->ADestadoimp; 
        !           636: 
        !           637:     if(matriz.Sdatoexp != NULL) grado->Sdatoexp = 1 / pasos->Sdatoexp; 
        !           638:     if(matriz.Sdir_exp != NULL) grado->Sdir_exp = 1 / pasos->Sdir_exp; 
        !           639:     if(matriz.Spilaexp != NULL) grado->Spilaexp = 1 / pasos->Spilaexp; 
        !           640:     if(matriz.Sestadoexp != NULL) grado->Sestadoexp = 1 / pasos->Sestadoexp; 
        !           641:         
        !           642:     if(matriz.Sdatoimp != NULL) grado->Sdatoimp = 1 / pasos->Sdatoimp; 
        !           643:     if(matriz.Sdir_imp != NULL) grado->Sdir_imp = 1 / pasos->Sdir_imp; 
        !           644:     if(matriz.Spilaimp != NULL) grado->Spilaimp = 1 / pasos->Spilaimp; 
        !           645:     if(matriz.Sestadoimp != NULL) grado->Sestadoimp = 1 / pasos->Sestadoimp; 
1.1       rico      646: 
1.2     ! rico      647:     if(matriz.D != NULL) grado->D = 1 / pasos->D; 
1.1       rico      648: }
                    649: 
                    650: */
                    651: 
                    652: 
                    653: 
                    654: /* esta función calcula el grado de paralelismo NORMALIZADO a partir de */
                    655: /* la dimensión de la ventana de instrucciones y de los pasos de computación */
                    656: 
                    657: void CalcularGradoParalelismoNormalizado(parametromatriz *pasos, parametromatriz *grado)
                    658: {
1.2     ! rico      659:     unsigned int dim;
1.1       rico      660: 
1.2     ! rico      661:     dim = configuracion.ventana;
        !           662:     
        !           663:     if(matriz.Ddatoexp != NULL) grado->Ddatoexp = InversoNormalizado(dim, pasos->Ddatoexp);
        !           664:     if(matriz.Ddir_exp != NULL) grado->Ddir_exp = InversoNormalizado(dim, pasos->Ddir_exp);
        !           665:     if(matriz.Dpilaexp != NULL) grado->Dpilaexp = InversoNormalizado(dim, pasos->Dpilaexp); 
        !           666:     if(matriz.Destadoexp != NULL) grado->Destadoexp = InversoNormalizado(dim, pasos->Destadoexp); 
        !           667:         
        !           668:     if(matriz.Ddatoimp != NULL) grado->Ddatoimp = InversoNormalizado(dim, pasos->Ddatoimp); 
        !           669:     if(matriz.Ddir_imp != NULL) grado->Ddir_imp = InversoNormalizado(dim, pasos->Ddir_imp); 
        !           670:     if(matriz.Dpilaimp != NULL) grado->Dpilaimp = InversoNormalizado(dim, pasos->Dpilaimp); 
        !           671:     if(matriz.Destadoimp != NULL) grado->Destadoimp = InversoNormalizado(dim, pasos->Destadoimp); 
        !           672: 
        !           673:     if(matriz.ADdatoexp != NULL) grado->ADdatoexp = InversoNormalizado(dim, pasos->ADdatoexp); 
        !           674:     if(matriz.ADdir_exp != NULL) grado->ADdir_exp = InversoNormalizado(dim, pasos->ADdir_exp); 
        !           675:     if(matriz.ADpilaexp != NULL) grado->ADpilaexp = InversoNormalizado(dim, pasos->ADpilaexp); 
        !           676:     if(matriz.ADestadoexp != NULL) grado->ADestadoexp = InversoNormalizado(dim, pasos->ADestadoexp); 
        !           677:         
        !           678:     if(matriz.ADdatoimp != NULL) grado->ADdatoimp = InversoNormalizado(dim, pasos->ADdatoimp); 
        !           679:     if(matriz.ADdir_imp != NULL) grado->ADdir_imp = InversoNormalizado(dim, pasos->ADdir_imp); 
        !           680:     if(matriz.ADpilaimp != NULL) grado->ADpilaimp = InversoNormalizado(dim, pasos->ADpilaimp); 
        !           681:     if(matriz.ADestadoimp != NULL) grado->ADestadoimp = InversoNormalizado(dim, pasos->ADestadoimp); 
        !           682: 
        !           683:     if(matriz.Sdatoexp != NULL) grado->Sdatoexp = InversoNormalizado(dim, pasos->Sdatoexp); 
        !           684:     if(matriz.Sdir_exp != NULL) grado->Sdir_exp = InversoNormalizado(dim, pasos->Sdir_exp); 
        !           685:     if(matriz.Spilaexp != NULL) grado->Spilaexp = InversoNormalizado(dim, pasos->Spilaexp); 
        !           686:     if(matriz.Sestadoexp != NULL) grado->Sestadoexp = InversoNormalizado(dim, pasos->Sestadoexp); 
        !           687:         
        !           688:     if(matriz.Sdatoimp != NULL) grado->Sdatoimp = InversoNormalizado(dim, pasos->Sdatoimp); 
        !           689:     if(matriz.Sdir_imp != NULL) grado->Sdir_imp = InversoNormalizado(dim, pasos->Sdir_imp); 
        !           690:     if(matriz.Spilaimp != NULL) grado->Spilaimp = InversoNormalizado(dim, pasos->Spilaimp); 
        !           691:     if(matriz.Sestadoimp != NULL) grado->Sestadoimp = InversoNormalizado(dim, pasos->Sestadoimp); 
1.1       rico      692: 
1.2     ! rico      693:     if(matriz.D != NULL) grado->D = InversoNormalizado(dim, pasos->D); 
1.1       rico      694: }
                    695: 
                    696: 
                    697: /* esta función calcula el acoplamiento de cada matriz de dependencias */
                    698: 
                    699: void CalcularAcoplamiento(parametromatriz *acoplamiento)
                    700: {
1.2     ! rico      701:     if(matriz.Ddatoexp != NULL) acoplamiento->Ddatoexp = Acoplamiento(matriz.Ddatoexp);
        !           702:     if(matriz.Ddir_exp != NULL) acoplamiento->Ddir_exp = Acoplamiento(matriz.Ddir_exp);
        !           703:     if(matriz.Dpilaexp != NULL) acoplamiento->Dpilaexp = Acoplamiento(matriz.Dpilaexp); 
        !           704:     if(matriz.Destadoexp != NULL) acoplamiento->Destadoexp = Acoplamiento(matriz.Destadoexp); 
        !           705:         
        !           706:     if(matriz.Ddatoimp != NULL) acoplamiento->Ddatoimp = Acoplamiento(matriz.Ddatoimp); 
        !           707:     if(matriz.Ddir_imp != NULL) acoplamiento->Ddir_imp = Acoplamiento(matriz.Ddir_imp); 
        !           708:     if(matriz.Dpilaimp != NULL) acoplamiento->Dpilaimp = Acoplamiento(matriz.Dpilaimp); 
        !           709:     if(matriz.Destadoimp != NULL) acoplamiento->Destadoimp = Acoplamiento(matriz.Destadoimp); 
        !           710: 
        !           711:     if(matriz.ADdatoexp != NULL) acoplamiento->ADdatoexp = Acoplamiento(matriz.ADdatoexp); 
        !           712:     if(matriz.ADdir_exp != NULL) acoplamiento->ADdir_exp = Acoplamiento(matriz.ADdir_exp); 
        !           713:     if(matriz.ADpilaexp != NULL) acoplamiento->ADpilaexp = Acoplamiento(matriz.ADpilaexp); 
        !           714:     if(matriz.ADestadoexp != NULL) acoplamiento->ADestadoexp = Acoplamiento(matriz.ADestadoexp); 
        !           715:         
        !           716:     if(matriz.ADdatoimp != NULL) acoplamiento->ADdatoimp = Acoplamiento(matriz.ADdatoimp); 
        !           717:     if(matriz.ADdir_imp != NULL) acoplamiento->ADdir_imp = Acoplamiento(matriz.ADdir_imp); 
        !           718:     if(matriz.ADpilaimp != NULL) acoplamiento->ADpilaimp = Acoplamiento(matriz.ADpilaimp); 
        !           719:     if(matriz.ADestadoimp != NULL) acoplamiento->ADestadoimp = Acoplamiento(matriz.ADestadoimp); 
        !           720: 
        !           721:     if(matriz.Sdatoexp != NULL) acoplamiento->Sdatoexp = Acoplamiento(matriz.Sdatoexp); 
        !           722:     if(matriz.Sdir_exp != NULL) acoplamiento->Sdir_exp = Acoplamiento(matriz.Sdir_exp); 
        !           723:     if(matriz.Spilaexp != NULL) acoplamiento->Spilaexp = Acoplamiento(matriz.Spilaexp); 
        !           724:     if(matriz.Sestadoexp != NULL) acoplamiento->Sestadoexp = Acoplamiento(matriz.Sestadoexp); 
        !           725:         
        !           726:     if(matriz.Sdatoimp != NULL) acoplamiento->Sdatoimp = Acoplamiento(matriz.Sdatoimp); 
        !           727:     if(matriz.Sdir_imp != NULL) acoplamiento->Sdir_imp = Acoplamiento(matriz.Sdir_imp); 
        !           728:     if(matriz.Spilaimp != NULL) acoplamiento->Spilaimp = Acoplamiento(matriz.Spilaimp); 
        !           729:     if(matriz.Sestadoimp != NULL) acoplamiento->Sestadoimp = Acoplamiento(matriz.Sestadoimp); 
1.1       rico      730: 
1.2     ! rico      731:     if(matriz.D != NULL) acoplamiento->D = (double) Acoplamiento(matriz.D); 
1.1       rico      732: }
                    733: 
                    734: 
                    735: 
                    736: /* esta función reserva memoria para salvar el histograma de pasos de computación */
                    737: /* asociado a la matriz de dependencias de datos D (no el resto) */
                    738: 
                    739: void CrearHistogramaPasos()
                    740: {
1.2     ! rico      741:     char mensaje[MAX_LINE];
1.1       rico      742: 
1.2     ! rico      743:     distribucionpasos = calloc(configuracion.ventana+1, sizeof(unsigned long));
1.1       rico      744:     if (distribucionpasos == NULL)
                    745:     {
                    746:         sprintf(mensaje, "[CrearHistogramaPasos] Memoria insuficiente");
1.2     ! rico      747:         Notificar(mensaje, ERROR_SALIR, ECO_NO);
        !           748:         /* el programa finaliza si no hay memoria suficiente */
1.1       rico      749:     }
                    750: }
                    751: 
                    752: 
                    753: /* inicia el histograma a 0 (con la reserva de calloc no es necesario) */
                    754: 
                    755: void IniciarHistogramaPasos()
                    756: {
1.2     ! rico      757:     unsigned int i;
1.1       rico      758: 
1.2     ! rico      759:     for(i=0; i<configuracion.ventana; i++) distribucionpasos[i] = 0;
1.1       rico      760: }
                    761: 
                    762: 
                    763: /* libera la memoria reservada para el histograma */
                    764: 
                    765: void LiberarMemoriaHistogramaPasos()
                    766: {
1.2     ! rico      767:     free(distribucionpasos);
1.1       rico      768: }
                    769: 
                    770: 
                    771: /* actualiza los datos del histograma */
                    772: 
                    773: void ActualizarHistogramaPasos()
                    774: {
1.2     ! rico      775:     distribucionpasos[(unsigned int)pasos->D]++;
1.1       rico      776: }
                    777: 

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