1 /*
2 * rand-uniform.c
3 *
4 * Custom variable implementation that returns uniformly distributed random
5 * numbers.
6 *
7 * Author: Santhosh Kumar Koundinya (santhosh@fsl.cs.sunysb.edu)
8 */
9
10 #include <stdio.h>
11 #include "mtwist/mtwist.h"
12 #include "mtwist/randistrs.h"
13 #include "cvar.h"
14 #include "cvar_trace.h"
15 #include "cvar_tokens.h"
16 #include "cvar-uniform.h"
17
cvar_alloc_handle(const char * cvar_parameters,void * (* cvar_malloc)(size_t size),void (* cvar_free)(void * cvar_ptr))18 void *cvar_alloc_handle(const char *cvar_parameters,
19 void *(*cvar_malloc)(size_t size), void (*cvar_free)(void *cvar_ptr))
20 {
21 cvar_token_t *list_head;;
22 cvar_token_t *t;
23 handle_t handle;
24 handle_t *state = NULL;
25 int ret = 0;
26
27 cvar_trace("entry");
28
29 /* Tokenize parameters supplied by filebench. */
30 list_head = NULL;
31 ret = tokenize(cvar_parameters, DEFAULT_PARAMETER_DELIMITER,
32 DEFAULT_KEY_VALUE_DELIMITER, &list_head);
33 if (ret)
34 goto out;
35
36 /* Get the values for lower and upper. */
37 t = find_token(list_head, RU_LOWER);
38 if (t && t->value) {
39 t->used = 1;
40 handle.lower = atof(t->value);
41 } else
42 handle.lower = RU_LOWER_DEFAULT;
43
44 t = find_token(list_head, RU_UPPER);
45 if (t && t->value) {
46 t->used = 1;
47 handle.upper = atof(t->value);
48 } else
49 handle.upper = RU_UPPER_DEFAULT;
50
51 cvar_trace("lower = %lf, upper = %lf", handle.lower, handle.upper);
52
53 /* Validate parameters. */
54 if (handle.lower > handle.upper) {
55 cvar_log_error("Invalid parameter values: lower = %lf and upper = %lf. "
56 "upper must be greater than lower", handle.lower, handle.upper);
57 }
58
59 t = unused_tokens(list_head);
60 if (t) {
61 cvar_log_error("Unsupported parameter %s", t->key);
62 goto out;
63 }
64
65 /* Seed the state. */
66 mts_goodseed(&handle.state);
67
68 /* All set. Now allocate space for the handle in the shared segment and
69 * copy the state over. */
70 state = (handle_t *) cvar_malloc(sizeof(handle_t));
71 if (!state) {
72 cvar_log_error("Out of memory");
73 goto out;
74 }
75
76 *state = handle;
77
78 out:
79 free_tokens(list_head);
80
81 cvar_trace("exit");
82 return state;
83 }
84
cvar_revalidate_handle(void * cvar_handle)85 int cvar_revalidate_handle(void *cvar_handle)
86 {
87 handle_t *h = (handle_t *) cvar_handle;
88
89 mts_mark_initialized(&h->state);
90
91 return 0;
92 }
93
cvar_next_value(void * cvar_handle,double * value)94 int cvar_next_value(void *cvar_handle, double *value)
95 {
96 handle_t *h = (handle_t *) cvar_handle;
97
98 if (!h) {
99 cvar_log_error("NULL cvar_handle");
100 return -1;
101 }
102
103 if (!value) {
104 cvar_log_error("NULL value");
105 return -1;
106 }
107
108 *value = rds_uniform(&h->state, h->lower, h->upper);
109
110 return 0;
111 }
112
cvar_free_handle(void * handle,void (* cvar_free)(void * ptr))113 void cvar_free_handle(void *handle, void (*cvar_free)(void *ptr))
114 {
115 cvar_free(handle);
116 }
117
cvar_usage()118 const char *cvar_usage()
119 {
120 int offset;
121
122 if (usage[0])
123 return usage;
124
125 offset = 0;
126
127 offset += snprintf(usage + offset, USAGE_LEN - offset,
128 "\tparameter\tdefault\n");
129 offset += snprintf(usage + offset, USAGE_LEN - offset,
130 "\t---------\t-------\n");
131
132 offset += snprintf(usage + offset, USAGE_LEN - offset,
133 "\t%s\t\t%.1f\n", RU_LOWER, RU_LOWER_DEFAULT);
134 offset += snprintf(usage + offset, USAGE_LEN - offset,
135 "\t%s\t\t%.1f\n", RU_UPPER, RU_UPPER_DEFAULT);
136
137 offset += snprintf(usage + offset, USAGE_LEN - offset,
138 "Use '%c' to delimit parameters and '%c' to delimit key-value "
139 "pairs.\n", DEFAULT_PARAMETER_DELIMITER,
140 DEFAULT_KEY_VALUE_DELIMITER);
141 offset += snprintf(usage + offset, USAGE_LEN - offset,
142 "Example: '%s%c%.1f%c%s%c%.1f'",
143 RU_LOWER, DEFAULT_KEY_VALUE_DELIMITER, RU_LOWER_DEFAULT,
144 DEFAULT_PARAMETER_DELIMITER,
145 RU_UPPER, DEFAULT_KEY_VALUE_DELIMITER, RU_UPPER_DEFAULT);
146
147 return usage;
148 }
149
cvar_version()150 const char *cvar_version()
151 {
152 return VERSION;
153 }
154