fixed config.h include
[libfirm] / ir / stat / distrib.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/distrib.c
4  * Purpose:     Statistics for Firm. Distribution tables.
5  * Author:      Michael Beck
6  * Created:
7  * CVS-ID:      $Id$
8  * Copyright:   (c) 2004 Universität Karlsruhe
9  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
10  */
11 #ifdef HAVE_CONFIG_H
12 # include "config.h"
13 #endif
14
15 #include "hashptr.h"
16 #include "xmalloc.h"
17 #include "firmstat_t.h"
18
19 /**
20  * calculates a hash value for an address
21  */
22 static unsigned addr_hash(const void *object)
23 {
24   return HASH_PTR(object);
25 }
26
27 /**
28  * calculates a hash value for an integer
29  */
30 static unsigned int_hash(const void *object)
31 {
32   return (unsigned)object;
33 }
34
35 /**
36  * compare function for integer distribution tables
37  */
38 static int int_cmp_fun(const void *elt, const void *key)
39 {
40   int p1 = (int)elt;
41   int p2 = (int)key;
42
43   return p1 - p2;
44 }
45
46 /*
47  * create a new distribution table
48  */
49 distrib_tbl_t *stat_new_distrib_tbl(pset_cmp_fun cmp_func, distrib_hash_fun hash_func)
50 {
51   distrib_tbl_t *res;
52
53   res = xmalloc(sizeof(*res));
54
55   obstack_init(&res->cnts);
56
57   /* create the hash-table */
58   res->hash_map  = new_pset(cmp_func, 8);
59   res->hash_func = hash_func ? hash_func : addr_hash;
60   res->int_dist  = 0;
61
62   return res;
63 }
64
65 /*
66  * create a new distribution table for an integer distribution
67  */
68 distrib_tbl_t *stat_new_int_distrib_tbl(void)
69 {
70   distrib_tbl_t *res = stat_new_distrib_tbl(int_cmp_fun, int_hash);
71
72   if (res)
73     res->int_dist = 1;
74
75   return res;
76 }
77
78 /*
79  * destroy a distribution table
80  */
81 void stat_delete_distrib_tbl(distrib_tbl_t *tbl)
82 {
83   if (tbl) {
84     /* free all entries */
85     obstack_free(&tbl->cnts, NULL);
86
87     /* delete the hash table */
88     del_pset(tbl->hash_map);
89   }
90 }
91
92 /**
93  * Returns the associates distrib_entry_t for an object
94  */
95 static distrib_entry_t *distrib_get_entry(distrib_tbl_t *tbl, const void *object)
96 {
97   distrib_entry_t key;
98   distrib_entry_t *elem;
99
100   key.object = object;
101
102   elem = pset_find(tbl->hash_map, &key, tbl->hash_func(object));
103   if (elem)
104     return elem;
105
106   elem = obstack_alloc(&tbl->cnts, sizeof(*elem));
107
108   /* clear counter */
109   cnt_clr(&elem->cnt);
110
111   elem->object = object;
112
113   return pset_insert(tbl->hash_map, elem, tbl->hash_func(object));
114 }
115
116 /*
117  * adds a new object count into the distribution table
118  */
119 void stat_add_distrib_tbl(distrib_tbl_t *tbl, const void *object, const counter_t *cnt)
120 {
121   distrib_entry_t *elem = distrib_get_entry(tbl, object);
122
123   cnt_add(&elem->cnt, cnt);
124 }
125
126 /**
127  * adds a new key count into the integer distribution table
128  */
129 void stat_add_int_distrib_tbl(distrib_tbl_t *tbl, int key, const counter_t *cnt)
130 {
131    stat_add_distrib_tbl(tbl, (const void *)key, cnt);
132 }
133
134 /*
135  * calculates the mean value of a distribution
136  */
137 double stat_calc_mean_distrib_tbl(distrib_tbl_t *tbl)
138 {
139   distrib_entry_t *entry;
140   unsigned count;
141   double sum;
142
143   if (tbl->int_dist) {
144     /* integer distribution, need min, max */
145     int min, max;
146
147     entry = pset_first(tbl->hash_map);
148
149     if (! entry)
150       return 0.0;
151
152     min =
153     max = (int)entry->object;
154     sum = cnt_to_dbl(&entry->cnt);
155
156
157     for (entry = pset_next(tbl->hash_map); entry; entry = pset_next(tbl->hash_map)) {
158       int value = (int)entry->object;
159
160       if (value < min)
161         min = value;
162       if (value > max);
163         max = value;
164
165       sum += cnt_to_dbl(&entry->cnt);
166     }
167     count = max - min + 1;
168   }
169   else {
170     sum = 0.0;
171     count = 0;
172     for (entry = pset_first(tbl->hash_map); entry; entry = pset_next(tbl->hash_map)) {
173       sum += cnt_to_dbl(&entry->cnt);
174       ++count;
175     }
176   }
177
178   return count ? sum / (double)count : 0.0;
179 }
180
181 /**
182  * iterates over all entries in a distribution table
183  */
184 void stat_iterate_distrib_tbl(distrib_tbl_t *tbl, eval_distrib_entry_fun eval)
185 {
186   distrib_entry_t *entry;
187
188   for (entry = pset_first(tbl->hash_map); entry; entry = pset_next(tbl->hash_map)) {
189     eval(entry);
190   }
191 }