1 /*
2  * rand-lognormal.c
3  *
4  * Custom variable implementation that returns Log-Normally 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-lognormal.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 value of shape and scale. */
37 	t = find_token(list_head, RLN_SHAPE);
38 	if (t && t->value) {
39 		t->used = 1;
40 		handle.shape = atof(t->value);
41 	} else
42 		handle.shape = RLN_SHAPE_DEFAULT;
43 
44 	t = find_token(list_head, RLN_SCALE);
45 	if (t && t->value) {
46 		t->used = 1;
47 		handle.scale = atof(t->value);
48 	} else
49 		handle.scale = RLN_SCALE_DEFAULT;
50 
51 	cvar_trace("shape = %lf, scale = %lf", handle.shape, handle.scale);
52 
53 	if (handle.shape < 0) {
54 		cvar_log_error("Invalid parameter value: shape = %lf. shape is a "
55 				"non-zero, positive rational number", handle.shape);
56 		goto out;
57 	}
58 
59 	if (handle.scale < 0) {
60 		cvar_log_error("Invalid parameter value: scale = %lf. scale is a "
61 				"non-zero, positive rational number", handle.scale);
62 		goto out;
63 	}
64 
65 	t = unused_tokens(list_head);
66 	if (t) {
67 		cvar_log_error("Unsupported parameter %s", t->key);
68 		goto out;
69 	}
70 
71 	/* Seed the state. */
72 	mts_goodseed(&handle.state);
73 
74 	/* All set. Now allocate space for the handle in the shared segment and
75 	 * copy the state over. */
76 	state = (handle_t *) cvar_malloc(sizeof(handle_t));
77 	if (!state) {
78 		cvar_log_error("Out of memory");
79 		goto out;
80 	}
81 
82 	*state = handle;
83 
84 out:
85 	free_tokens(list_head);
86 
87 	cvar_trace("exit");
88 	return state;
89 }
90 
cvar_revalidate_handle(void * cvar_handle)91 int cvar_revalidate_handle(void *cvar_handle)
92 {
93 	handle_t *h = (handle_t *) cvar_handle;
94 
95 	mts_mark_initialized(&h->state);
96 
97 	return 0;
98 }
99 
cvar_next_value(void * cvar_handle,double * value)100 int cvar_next_value(void *cvar_handle, double *value)
101 {
102 	handle_t *h = (handle_t *) cvar_handle;
103 
104 	if (!h) {
105 		cvar_trace("NULL cvar_handle");
106 		return -1;
107 	}
108 
109 	if (!value) {
110 		cvar_trace("NULL value");
111 		return -1;
112 	}
113 
114 	*value = rds_lognormal(&h->state, h->shape, h->scale);
115 
116 	return 0;
117 }
118 
cvar_free_handle(void * handle,void (* cvar_free)(void * ptr))119 void cvar_free_handle(void *handle, void (*cvar_free)(void *ptr))
120 {
121 	cvar_free(handle);
122 }
123 
cvar_usage()124 const char *cvar_usage()
125 {
126 	int offset;
127 
128 	if (usage[0])
129 		return usage;
130 
131 	offset = 0;
132 
133 	offset += snprintf(usage + offset, USAGE_LEN - offset,
134 			"\tparameter\tdefault\n");
135 	offset += snprintf(usage + offset, USAGE_LEN - offset,
136 			"\t---------\t-------\n");
137 
138 	offset += snprintf(usage + offset, USAGE_LEN - offset,
139 			"\t%s\t\t%.1f\n", RLN_SHAPE, RLN_SHAPE_DEFAULT);
140 	offset += snprintf(usage + offset, USAGE_LEN - offset,
141 			"\t%s\t\t%.1f\n", RLN_SCALE, RLN_SCALE_DEFAULT);
142 
143 	offset += snprintf(usage + offset, USAGE_LEN - offset,
144 			"Use '%c' to delimit parameters and '%c' to delimit key-value "
145 			"pairs.\n", DEFAULT_PARAMETER_DELIMITER,
146 			DEFAULT_KEY_VALUE_DELIMITER);
147 
148 	offset += snprintf(usage + offset, USAGE_LEN - offset,
149 			"Example: '%s%c%.1f%c%s%c%.1f'",
150 			RLN_SHAPE, DEFAULT_KEY_VALUE_DELIMITER, RLN_SHAPE_DEFAULT,
151 			DEFAULT_PARAMETER_DELIMITER,
152 			RLN_SCALE, DEFAULT_KEY_VALUE_DELIMITER, RLN_SCALE_DEFAULT);
153 
154 	return usage;
155 }
156 
cvar_version()157 const char *cvar_version()
158 {
159 	return VERSION;
160 }
161