📄 statistics.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * */#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#include <math.h>#include <float.h>#include "simtypes.h"#include "sim_error.h"#include "simutil.h" #include "annotations.h"#include "cpu_interface.h"#include "statistics.h"#include "tcl_init.h"#define MIN(_x, _y) (((_x) < (_y)) ? (_x) : (_y))#define MAX(_x, _y) (((_x) > (_y)) ? (_x) : (_y))#define MAX_STATS_STRLEN 64static Tcl_HashTable names;static int cmdCreate(Tcl_Interp *interp, int argc, char *argv[]);static int cmdEntry(Tcl_Interp *interp, int argc, char *argv[]);static int cmdList(Tcl_Interp *interp, int argc, char *argv[]);static int cmdReset(Tcl_Interp *interp, int argc, char *argv[]);static void StatsReset(Stats *stat);static tclcmd statCmds[] = {{ "create", -1, cmdCreate, " create name ?numbuckets minval incr?"},{ "entry", -1, cmdEntry, " entry name x ?y?"},{ "list", -1, cmdList, " list ?name?"},{ "reset", -1, cmdReset, " reset name"},{ NULL, 0, NULL, NULL}};void StatisticsInit(Tcl_Interp *interp){ Tcl_InitHashTable(&names, TCL_STRING_KEYS); Tcl_CreateCommand(interp, "statistics", DispatchCmd, (ClientData)statCmds, NULL); }int cmdCreate(Tcl_Interp *interp, int argc, char *argv[]){ Stats *stat; char *name; Tcl_HashEntry *entry; int new = 0; int code; int numb; double minval, incr; if (argc == 3) { numb = 0; minval = 0.0; incr = 0.0; } else if (argc == 6) { if ((code = Tcl_GetInt(interp, argv[3], &numb)) != TCL_OK) { return code; } if ((code = Tcl_GetDouble(interp, argv[4], &minval)) != TCL_OK) { Tcl_AppendResult(interp, "bad arg 3: should be int", NULL); return code; } if ((code = Tcl_GetDouble(interp, argv[5], &incr)) != TCL_OK) { Tcl_AppendResult(interp, "bad arg 3: should be int", NULL); return code; } } else { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], statCmds[0].usage, "\"", NULL); return TCL_ERROR; } name = argv[2]; entry = Tcl_CreateHashEntry(&names, name, &new); if (!new) { Tcl_AppendResult(interp, "stat name already taken \"", name, "\"", NULL); return TCL_ERROR; } stat = StatsCreate(numb, minval, incr); Tcl_SetHashValue(entry, stat); return TCL_OK;}int cmdEntry(Tcl_Interp *interp, int argc, char *argv[]){ Stats *stat; char *name; Tcl_HashEntry *entry; double x, y = 1.0; int new = 0; if ((argc != 4) && (argc != 5)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], statCmds[1].usage, "\"", NULL); return TCL_ERROR; } name = argv[2]; entry = Tcl_FindHashEntry(&names, name); if (!entry) { entry = Tcl_CreateHashEntry(&names, name, &new); stat = StatsCreate(0, 0, 0); Tcl_SetHashValue(entry, stat); } if (Tcl_GetDouble(interp, argv[3], &x) != TCL_OK) { Tcl_AppendResult(interp, "expected a double: \"", argv[3], "\"", NULL); return TCL_ERROR; } if ((argc == 5) && (Tcl_GetDouble(interp, argv[4], &y) != TCL_OK)) { Tcl_AppendResult(interp, "expected a double: \"", argv[4], "\"", NULL); return TCL_ERROR; } stat = (Stats *)Tcl_GetHashValue(entry); StatsEntry(stat, x, y); return TCL_OK;}int cmdReset(Tcl_Interp *interp, int argc, char *argv[]){ Stats *stat; char *name; Tcl_HashEntry *entry; int new = 0; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], statCmds[3].usage, "\"", NULL); return TCL_ERROR; } name = argv[2]; entry = Tcl_FindHashEntry(&names, name); if (!entry) { entry = Tcl_CreateHashEntry(&names, name, &new); stat = StatsCreate(0, 0, 0); Tcl_SetHashValue(entry, stat); } stat = (Stats *)Tcl_GetHashValue(entry); StatsReset(stat); return TCL_OK;}static voidStatsPrintTcl(Tcl_Interp *interp, Stats *stat){ char buf[MAX_STATS_STRLEN]; int i; sprintf(buf, "n %d ", stat->num); Tcl_AppendResult(interp, buf, NULL); sprintf(buf, "sumX %.3f ", stat->sumX); Tcl_AppendResult(interp, buf, NULL); sprintf(buf, "sumY %.3f ", stat->sumY); Tcl_AppendResult(interp, buf, NULL); sprintf(buf, "sumXX %.3f ", stat->sumXsq); Tcl_AppendResult(interp, buf, NULL); sprintf(buf, "sumYY %.3f ", stat->sumYsq); Tcl_AppendResult(interp, buf, NULL); sprintf(buf, "sumXY %.3f ", stat->sumXY); Tcl_AppendResult(interp, buf, NULL); if (stat->minX == DBL_MAX) { Tcl_AppendResult(interp, "minX NA ", NULL); } else { sprintf(buf, "minX %.3f ", stat->minX); Tcl_AppendResult(interp, buf, NULL); } if (stat->maxX == -DBL_MAX) { Tcl_AppendResult(interp, "maxX NA ", NULL); } else { sprintf(buf, "maxX %.3f ", stat->maxX); Tcl_AppendResult(interp, buf, NULL); } if (stat->minY == DBL_MAX) { Tcl_AppendResult(interp, "minY NA ", NULL); } else { sprintf(buf, "minY %.3f ", stat->minY); Tcl_AppendResult(interp, buf, NULL); } if (stat->maxY == -DBL_MAX) { Tcl_AppendResult(interp, "maxY NA ", NULL); } else { sprintf(buf, "maxY %.3f ", stat->maxY); Tcl_AppendResult(interp, buf, NULL); } if (stat->numBuckets) { sprintf(buf, "numbucket %d ", stat->numBuckets); Tcl_AppendResult(interp, buf, NULL); sprintf(buf, "minval %.3f ", stat->minVal); Tcl_AppendResult(interp, buf, NULL); sprintf(buf, "incr %.3f ", stat->increment); Tcl_AppendResult(interp, buf, "buckets", NULL); for (i=0; i<(stat->numBuckets+2); i++) { sprintf(buf, "%.3f ", stat->buckets[i]); Tcl_AppendResult(interp, buf, NULL); } }} int cmdList(Tcl_Interp *interp, int argc, char *argv[]){ Stats *stat; char *name; Tcl_HashEntry *entry; if (argc < 2 && argc > 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], statCmds[2].usage, "\"", NULL); return TCL_ERROR; } if (argc == 2) { Tcl_HashSearch search; for (entry = Tcl_FirstHashEntry(&names,&search); entry != NULL; entry = Tcl_NextHashEntry(&search)) { char *name = Tcl_GetHashKey(&names,entry); Stats *stat = (Stats *)Tcl_GetHashValue(entry); Tcl_AppendResult(interp, "STATS: ", name, " ", NULL); StatsPrintTcl(interp,stat); Tcl_AppendResult(interp, "\n", NULL); } } else { name = argv[2]; entry = Tcl_FindHashEntry(&names, name); if (!entry) { Tcl_AppendResult(interp, "statistics \"", name, " is not defined\"", NULL); return TCL_ERROR; } stat = (Stats *)Tcl_GetHashValue(entry); StatsPrintTcl(interp,stat); } return TCL_OK;}Stats *StatsCreate(int numBuckets, double minValue, double increment){ Stats *stat = (Stats*)ZMALLOC(sizeof(Stats),"StatsCreate"); ASSERT(stat); stat->numBuckets = numBuckets; stat->minVal = minValue; stat->increment = increment; if (numBuckets) { stat->buckets = (double*)ZMALLOC(sizeof(double) * (numBuckets+2), "statsBucket"); } else { stat->buckets = NULL; } StatsReset(stat); return stat;}static void StatsReset(Stats *stat){ stat->num = 0; stat->sumX = 0; stat->sumY = 0; stat->sumXsq = 0; stat->sumYsq = 0; stat->sumXY = 0; stat->minX = DBL_MAX; stat->maxX = -DBL_MAX; stat->minY = DBL_MAX; stat->maxY = -DBL_MAX; if (stat->numBuckets) { int i; for (i=0; i<stat->numBuckets+2; i++) { stat->buckets[i] = 0; } }}void StatsDestroy(Stats *stat){ ASSERT(stat); if (stat->numBuckets) { ASSERT(stat->buckets); free(stat->buckets); } free(stat);}void StatsEntry(Stats *stat, double x, double y){ stat->num++; stat->sumX += x; stat->sumY += y; stat->sumXsq += x*x; stat->sumYsq += y*y; stat->sumXY += x*y; stat->minX = MIN(stat->minX, x); stat->maxX = MAX(stat->maxX, x); stat->minY = MIN(stat->minY, y); stat->maxY = MAX(stat->maxY, y); if (stat->numBuckets) { int bnum; ASSERT(stat->buckets); if (x < stat->minVal) { bnum = 0; } else if (x >= (stat->minVal + (stat->numBuckets * stat->increment))) { bnum = stat->numBuckets + 1; } else { bnum = ((x - stat->minVal) / stat->increment) + 1; } ASSERT((bnum >= 0) && (bnum <= (stat->numBuckets+1))); stat->buckets[bnum] += y; }}void StatsTransfer(Stats *src, Stats *dest){ int i; dest->num += src->num; dest->sumX += src->sumX; dest->sumY += src->sumY; dest->sumXsq += src->sumXsq; dest->sumYsq += src->sumYsq; dest->minX = MIN(dest->minX, src->minX); dest->maxX = MAX(dest->maxX, src->maxX); dest->minY = MIN(dest->minY, src->minY); dest->maxY = MAX(dest->maxY, src->maxY); ASSERT(src->numBuckets == dest->numBuckets); if (dest->numBuckets) { for (i=0; i<(dest->numBuckets+2); i++) { dest->buckets[i] += src->buckets[i]; } }}void StatsList(Stats *stat, char *leader){ int i; char buf[MAX_STATS_STRLEN]; ASSERT(stat); sprintf(buf, "n %d\n", stat->num); Tcl_AppendResult(TCLInterp, buf, NULL); if (stat->num) { Tcl_AppendResult(TCLInterp, leader, NULL); sprintf(buf, "sumX %.2f ", stat->sumX); Tcl_AppendResult(TCLInterp, buf, NULL); sprintf(buf, "sumY %.2f ", stat->sumY); Tcl_AppendResult(TCLInterp, buf, NULL); sprintf(buf, "sumXX %.2f ", stat->sumXsq); Tcl_AppendResult(TCLInterp, buf, NULL); sprintf(buf, "sumYY %.2f ", stat->sumYsq); Tcl_AppendResult(TCLInterp, buf, NULL); sprintf(buf, "sumXY %.2f ", stat->sumXY); Tcl_AppendResult(TCLInterp, buf, NULL); sprintf(buf, "minX %.2f ", stat->minX); Tcl_AppendResult(TCLInterp, buf, NULL); sprintf(buf, "maxX %.2f ", stat->maxX); Tcl_AppendResult(TCLInterp, buf, NULL); sprintf(buf, "minY %.2f ", stat->minY); Tcl_AppendResult(TCLInterp, buf, NULL); sprintf(buf, "maxY %.2f ", stat->maxY); Tcl_AppendResult(TCLInterp, buf, NULL); if (stat->numBuckets) { sprintf(buf, "numbucket %d ", stat->numBuckets); Tcl_AppendResult(TCLInterp, buf, NULL); sprintf(buf, "minval %f ", stat->minVal); Tcl_AppendResult(TCLInterp, buf, NULL); sprintf(buf, "incr %f ", stat->increment); Tcl_AppendResult(TCLInterp, buf, NULL); for (i=0; i<(stat->numBuckets+2); i++) { sprintf(buf, "%.2f ", stat->buckets[i]); Tcl_AppendResult(TCLInterp, buf, NULL); } } Tcl_AppendResult(TCLInterp, "\n", NULL); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -