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