| Commit | Line | Data |
|---|---|---|
| d0213500 | 1 | #include <assert.h> |
| 2 | #include <fenv.h> | |
| 3 | #include <stdio.h> | |
| d0213500 | 4 | #include <time.h> |
| 5 | #include <sys/time.h> | |
| 6 | ||
| 7 | /* Function prototypes */ | |
| 8a5c9a9e | 8 | static int prof_clearexcept_all(size_t iterations); |
| 9 | static int prof_clearexcept_random(size_t iterations); | |
| 10 | static int prof_getenv(size_t iterations); | |
| 19258048 | 11 | static int prof_getround(size_t iterations); |
| 22d17f71 | 12 | static int prof_holdexcept(size_t iterations); |
| 16ffbff5 | 13 | static int prof_raiseexcept(size_t iterations); |
| 8a5c9a9e | 14 | static int prof_setenv_default(size_t iterations); |
| 8a5c9a9e | 15 | static int prof_setenv_getenv(size_t iterations); |
| 19258048 | 16 | static int prof_setround(size_t iterations); |
| 16ffbff5 | 17 | static int prof_updateenv_default(size_t iterations); |
| 8a5c9a9e | 18 | static int prof_updateenv_getenv(size_t iterations); |
| d0213500 | 19 | |
| 16ffbff5 | 20 | |
| 24e891a5 | 21 | /* Constants and macros */ |
| 19258048 | 22 | #define ITERATIONS (10 * 1000 * 1000) |
| d0213500 | 23 | |
| 48288bbc | 24 | /* |
| 25 | * They are esentially the same, but we still define them as if | |
| 26 | * they were different, for conceptual consistency and clarity. | |
| 27 | */ | |
| 24e891a5 | 28 | #define MARK_START(tv1) \ |
| 29 | assert(gettimeofday(tv1, NULL) == 0); | |
| 30 | ||
| 31 | #define MARK_END(tv2) \ | |
| 32 | assert(gettimeofday(tv2, NULL) == 0); | |
| 33 | ||
| 34 | #define MSECS(tv1, tv2) \ | |
| 35 | (((tv2).tv_sec - (tv1).tv_sec ) * 1000 + \ | |
| 36 | ((tv2).tv_usec - (tv1).tv_usec) / 1000) | |
| 37 | ||
| 48e5dc4e | 38 | static int extable[] = { |
| 39 | #ifdef FE_DIVBYZERO | |
| 40 | FE_DIVBYZERO, | |
| 41 | #endif | |
| 42 | #ifdef FE_INEXACT | |
| 43 | FE_INEXACT, | |
| 44 | #endif | |
| 45 | #ifdef FE_INVALID | |
| 46 | FE_INVALID, | |
| 47 | #endif | |
| 48 | #ifdef FE_OVERFLOW | |
| 49 | FE_OVERFLOW, | |
| 50 | #endif | |
| 51 | #ifdef FE_UNDERFLOW | |
| 52 | FE_UNDERFLOW, | |
| 53 | #endif | |
| 54 | #ifdef FE_ALL_EXCEPT | |
| 55 | FE_ALL_EXCEPT | |
| 56 | #endif | |
| 57 | }; | |
| 58 | ||
| 16ffbff5 | 59 | struct pentry { |
| 60 | const char *p_desc; | |
| 61 | int (*p_func)(); | |
| 62 | size_t p_iter; | |
| 63 | } ptable[] = { | |
| 64 | { "feclearexcept() FE_ALL_EXCEPT", | |
| 65 | prof_clearexcept_all, | |
| 66 | ITERATIONS }, | |
| 67 | ||
| 68 | { "feclearexcept() random", | |
| 69 | prof_clearexcept_random, | |
| 70 | ITERATIONS }, | |
| 71 | ||
| 72 | { " fegetenv() ", | |
| 73 | prof_getenv, | |
| 74 | ITERATIONS }, | |
| 75 | ||
| 19258048 SK |
76 | { " fegetround() ", |
| 77 | prof_getround, | |
| 78 | ITERATIONS }, | |
| 79 | ||
| 22d17f71 SK |
80 | { " feholdexcept() ", |
| 81 | prof_holdexcept, | |
| 82 | ITERATIONS }, | |
| 83 | ||
| 19258048 SK |
84 | { "feraiseexcept() ", |
| 85 | prof_raiseexcept, | |
| 86 | ITERATIONS }, | |
| 16ffbff5 | 87 | |
| 88 | { " fesetenv() FE_DFL_ENV", | |
| 89 | prof_setenv_default, | |
| 90 | ITERATIONS }, | |
| 91 | ||
| 92 | { " fesetenv() random", | |
| 93 | prof_setenv_getenv, | |
| 94 | ITERATIONS }, | |
| 95 | ||
| 19258048 SK |
96 | { " fesetround() ", |
| 97 | prof_setround, | |
| 98 | ITERATIONS }, | |
| 99 | ||
| 16ffbff5 | 100 | { " feupdateenv() FE_DFL_ENV", |
| 101 | prof_updateenv_default, | |
| 102 | ITERATIONS }, | |
| 103 | ||
| 104 | { " feupdateenv() random", | |
| 105 | prof_updateenv_getenv, | |
| 106 | ITERATIONS }, | |
| 107 | ||
| 108 | { NULL, NULL, 0 } | |
| 109 | }; | |
| 110 | ||
| d0213500 | 111 | int |
| 112 | main(void) | |
| 113 | { | |
| 16ffbff5 | 114 | const struct pentry *p; |
| d0213500 | 115 | int msecs; |
| 116 | ||
| 16ffbff5 | 117 | for (p = ptable; p; p++) { |
| 118 | if (p->p_desc == NULL && p->p_func == NULL && p->p_iter == 0) | |
| 119 | break; | |
| 120 | ||
| 121 | msecs = p->p_func(p->p_iter); | |
| 122 | printf("%s: %5d msecs for %d iterations\n", | |
| 123 | p->p_desc, msecs, p->p_iter); | |
| 124 | } | |
| d0213500 | 125 | |
| 126 | return 0; | |
| 127 | } | |
| 128 | ||
| 129 | static int | |
| 8a5c9a9e | 130 | prof_clearexcept_all(size_t iterations) |
| edbb7e04 | 131 | { |
| 132 | struct timeval tv1, tv2; | |
| 16ffbff5 | 133 | size_t i; |
| edbb7e04 | 134 | |
| 135 | MARK_START(&tv1); | |
| 136 | ||
| 137 | for (i = 0; i < iterations; i++) | |
| 138 | assert(feclearexcept(FE_ALL_EXCEPT) == 0); | |
| 139 | ||
| 140 | MARK_END(&tv2); | |
| 141 | ||
| 142 | return MSECS(tv1, tv2); | |
| 143 | } | |
| 144 | ||
| 145 | static int | |
| 8a5c9a9e | 146 | prof_clearexcept_random(size_t iterations) |
| 48e5dc4e | 147 | { |
| edbb7e04 | 148 | struct timeval tv1, tv2; |
| edbb7e04 | 149 | size_t i, N; |
| 48e5dc4e | 150 | |
| 48e5dc4e | 151 | N = sizeof(extable) / sizeof(extable[0]); |
| 152 | assert(N != 0); | |
| 153 | ||
| 8a5c9a9e | 154 | MARK_START(&tv1); |
| 155 | ||
| edbb7e04 | 156 | for (i = 0; i < iterations; i++) |
| 157 | assert(feclearexcept(extable[i%N]) == 0); | |
| 48e5dc4e | 158 | |
| edbb7e04 | 159 | MARK_END(&tv2); |
| 48e5dc4e | 160 | |
| edbb7e04 | 161 | return MSECS(tv1, tv2); |
| 48e5dc4e | 162 | } |
| 163 | ||
| 164 | static int | |
| 8a5c9a9e | 165 | prof_getenv(size_t iterations) |
| d0213500 | 166 | { |
| 167 | struct timeval tv1, tv2; | |
| 24e891a5 | 168 | fenv_t env; |
| 169 | size_t i; | |
| 170 | ||
| 171 | MARK_START(&tv1); | |
| 172 | ||
| 173 | for (i = 0; i < iterations; i++) | |
| 174 | assert(fegetenv(&env) == 0); | |
| d0213500 | 175 | |
| 24e891a5 | 176 | MARK_END(&tv2); |
| 177 | ||
| 178 | return MSECS(tv1, tv2); | |
| 179 | } | |
| 180 | ||
| 181 | static int | |
| 19258048 SK |
182 | prof_getround(size_t iterations) |
| 183 | { | |
| 184 | struct timeval tv1, tv2; | |
| 185 | size_t i; | |
| 186 | ||
| 187 | MARK_START(&tv1); | |
| 188 | ||
| 189 | for (i = 0; i < iterations; i++) | |
| 190 | assert(fegetround() == 0); | |
| 191 | ||
| 192 | MARK_END(&tv2); | |
| 193 | ||
| 194 | return MSECS(tv1, tv2); | |
| 195 | } | |
| 196 | ||
| 197 | static int | |
| 22d17f71 SK |
198 | prof_holdexcept(size_t iterations) |
| 199 | { | |
| 200 | struct timeval tv1, tv2; | |
| 201 | fenv_t env; | |
| 202 | size_t i; | |
| 203 | ||
| 204 | MARK_START(&tv1); | |
| 205 | ||
| 206 | for (i = 0; i < iterations; i++) | |
| 207 | assert(feholdexcept(&env) == 0); | |
| 208 | ||
| 209 | MARK_END(&tv2); | |
| 210 | ||
| 211 | return MSECS(tv1, tv2); | |
| 212 | } | |
| 213 | ||
| 214 | static int | |
| 8a5c9a9e | 215 | prof_setenv_default(size_t iterations) |
| 24e891a5 | 216 | { |
| 217 | struct timeval tv1, tv2; | |
| 218 | size_t i; | |
| d0213500 | 219 | |
| 24e891a5 | 220 | MARK_START(&tv1); |
| d0213500 | 221 | |
| 24e891a5 | 222 | for (i = 0; i < iterations; i++) |
| 223 | assert(fesetenv(FE_DFL_ENV) == 0); | |
| d0213500 | 224 | |
| 24e891a5 | 225 | MARK_END(&tv2); |
| d0213500 | 226 | |
| 24e891a5 | 227 | return MSECS(tv1, tv2); |
| d0213500 | 228 | } |
| 229 | ||
| 230 | static int | |
| 16ffbff5 | 231 | prof_updateenv_default(size_t iterations) |
| d0213500 | 232 | { |
| 233 | struct timeval tv1, tv2; | |
| 24e891a5 | 234 | size_t i; |
| 24e891a5 | 235 | |
| 236 | MARK_START(&tv1); | |
| 237 | ||
| 238 | for (i = 0; i < iterations; i++) | |
| 239 | assert(feupdateenv(FE_DFL_ENV) == 0); | |
| 240 | ||
| 241 | MARK_END(&tv2); | |
| d0213500 | 242 | |
| 24e891a5 | 243 | return MSECS(tv1, tv2); |
| 244 | } | |
| 245 | ||
| 246 | static int | |
| 8a5c9a9e | 247 | prof_setenv_getenv(size_t iterations) |
| 24e891a5 | 248 | { |
| 249 | struct timeval tv1, tv2; | |
| 250 | fenv_t env; | |
| 251 | size_t i; | |
| 252 | ||
| 253 | MARK_START(&tv1); | |
| 254 | ||
| 255 | for (i = 0; i < iterations; i++) { | |
| 256 | assert(fegetenv(&env) == 0); | |
| 257 | assert(fesetenv(&env) == 0); | |
| 258 | } | |
| 259 | ||
| 260 | MARK_END(&tv2); | |
| 261 | ||
| 262 | return MSECS(tv1, tv2); | |
| 263 | } | |
| 264 | ||
| 265 | static int | |
| 19258048 SK |
266 | prof_setround(size_t iterations) |
| 267 | { | |
| 268 | const int rndmodes[] = { | |
| 269 | #ifdef FE_DOWNWARD | |
| 270 | FE_DOWNWARD, | |
| 271 | #endif | |
| 272 | #ifdef FE_TONEAREST | |
| 273 | FE_TONEAREST, | |
| 274 | #endif | |
| 275 | #ifdef FE_TOWARDZERO | |
| 276 | FE_TOWARDZERO, | |
| 277 | #endif | |
| 278 | #ifdef FE_UPWARD | |
| 279 | FE_UPWARD | |
| 280 | #endif | |
| 281 | }; | |
| 282 | const size_t N = sizeof(rndmodes) / sizeof(rndmodes[0]); | |
| 283 | struct timeval tv1, tv2; | |
| 284 | size_t i; | |
| 285 | ||
| 286 | MARK_START(&tv1); | |
| 287 | ||
| 288 | for (i = 0; i < iterations; i++) { | |
| 289 | assert(fesetround(rndmodes[i % N]) == 0); | |
| 290 | } | |
| 291 | ||
| 292 | MARK_END(&tv2); | |
| 293 | ||
| 294 | return MSECS(tv1, tv2); | |
| 295 | } | |
| 296 | ||
| 297 | static int | |
| 8a5c9a9e | 298 | prof_updateenv_getenv(size_t iterations) |
| 24e891a5 | 299 | { |
| 300 | struct timeval tv1, tv2; | |
| 301 | fenv_t env; | |
| 302 | size_t i; | |
| d0213500 | 303 | |
| 24e891a5 | 304 | MARK_START(&tv1); |
| d0213500 | 305 | |
| 24e891a5 | 306 | for (i = 0; i < iterations; i++) { |
| 307 | assert(fegetenv(&env) == 0); | |
| 308 | assert(feupdateenv(&env) == 0); | |
| 309 | } | |
| d0213500 | 310 | |
| 24e891a5 | 311 | MARK_END(&tv2); |
| d0213500 | 312 | |
| 24e891a5 | 313 | return MSECS(tv1, tv2); |
| d0213500 | 314 | } |
| 16ffbff5 | 315 | |
| 316 | static int | |
| 317 | prof_raiseexcept(size_t iterations) | |
| 318 | { | |
| 319 | struct timeval tv1, tv2; | |
| 320 | size_t i, N; | |
| 321 | ||
| 322 | N = sizeof(extable) / sizeof(extable[0]); | |
| 323 | assert(N > 0); | |
| 324 | ||
| 325 | MARK_START(&tv1); | |
| 326 | ||
| 327 | for (i = 0; i < iterations; i++) { | |
| 328 | assert(feraiseexcept(extable[i%N]) == 0); | |
| 329 | } | |
| 330 | ||
| 331 | MARK_END(&tv2); | |
| 332 | ||
| 333 | return MSECS(tv1, tv2); | |
| 334 | } |