1 /*
2 * Copyright (c) 1996 Otmar Lendl (lendl@cosy.sbg.ac.at)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted without a fee provided that the following
7 * conditions are met:
8 *
9 * 1. This software is only used for private, research, or academic
10 * purposes.
11 *
12 * 2. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 3. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * 4. Any changes made to this package must be submitted to the author.
20 * The legal status of the submitted changes must allow their inclusion
21 * into this package under this license.
22 *
23 * 5. Publications in the field of pseudorandom number generation, which
24 * made use of this package must include a reference to this package.
25 *
26 * Any use of this software in a commercial environment requires a
27 * written licence from the author. Contact Otmar Lendl
28 * (lendl@cosy.sbg.ac.at) to negotiate the terms.
29 *
30 * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
31 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
32 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
33 *
34 * IN NO EVENT SHALL OTMAR LENDL BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
35 * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
36 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR
37 * NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
38 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
39 * OF THIS SOFTWARE.
40 *
41 */
42 /*
43 *
44 * file.c PRNG by reading a file (ASCII/BINARY)
45 *
46 * Author: Otmar Lendl (lendl@cosy.sbg.ac.at)
47 *
48 * Last Modification: Fri Nov 15 17:51:39 MET 1996
49 *
50 */
51
52 /* Modification History:
53 14.11.96: kludge for systems which don't define SEEK_SET
54 13.8.96: First Version.
55 17.10.00: use GNU automake and autoconf
56 01/11/07: replaced prng.free by prng.destroy
57 */
58
59 #include "prng.h"
60 #include <config.h>
61
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <math.h> /* for floor() */
66
67 #ifndef SEEK_SET
68 #define SEEK_SET 0 /* Sunos seems to need it */
69 #endif
70
71 /*
72 * prng_file_reset: Reset a File.
73 *
74 * Input:
75 * gen: Pointer to a struct prng.
76 *
77 */
prng_file_reset(struct prng * gen)78 void prng_file_reset(struct prng *gen)
79 {
80 fseek(gen->data.file_data.file,0,SEEK_SET);
81 }
82
83
84 /*
85 * prng_afile_get_next: Get next number from ASCII File
86 *
87 * Input:
88 * gen: Pointer to a struct prng.
89 *
90 */
prng_afile_get_next(struct prng * gen)91 inline double prng_afile_get_next(struct prng *gen)
92 {
93 double d;
94 char line[64];
95
96 if (fgets(line,63,gen->data.file_data.file) == NULL)
97 {
98 fprintf(stderr,"End of PRN file %s. Starting all over again !\n",
99 gen->data.file_data.filename);
100 prng_file_reset(gen);
101
102 if (fgets(line,63,gen->data.file_data.file) == NULL)
103 {
104 fprintf(stderr,"Serious problems with the file. Giving up.\n");
105 exit(1);
106 }
107 }
108
109 d = atof(line);
110 return(d - floor(d)); /* make sure number is in range */
111 }
112
113 /*
114 * prng_afile_get_array: Fill an Array with ASCII File numbers, scaled to [0,1)
115 *
116 * Input:
117 * gen: Pointer to a struct prng.
118 *
119 * array: Where to put the numbers. ( double *array)
120 * n: Size of the array
121 *
122 */
prng_afile_get_array(struct prng * gen,double * array,int n)123 void prng_afile_get_array(struct prng *gen,double *array,int n)
124 {
125 int i;
126
127 for(i=0;i<n;array[i++] = prng_afile_get_next(gen));
128 }
129
130
131 /*
132 * prng_bfile_get_next: Get next number from BINARY File
133 *
134 * Input:
135 * gen: Pointer to a struct prng.
136 *
137 */
prng_bfile_get_next(struct prng * gen)138 inline double prng_bfile_get_next(struct prng *gen)
139 {
140 prng_num n;
141
142 if (fread((void *)&n,sizeof(n),1,gen->data.file_data.file) != 1)
143 {
144 fprintf(stderr,"End of PRN file %s. Starting all over again !\n",
145 gen->data.file_data.filename);
146 prng_file_reset(gen);
147
148 if (fread((void *)&n,sizeof(n),1,gen->data.file_data.file) != 1)
149 {
150 fprintf(stderr,"Serious problems with the file. Giving up.\n");
151 exit(1);
152 }
153 }
154
155 return( (double) n / (double) (PRNG_NUM_MAX));
156 }
157
158
159 /*
160 * prng_bfile_get_array: Fill an Array with BINARY File numbers
161 *
162 * Input:
163 * gen: Pointer to a struct prng.
164 *
165 * array: Where to put the numbers. ( double *array)
166 * n: Size of the array
167 *
168 */
prng_bfile_get_array(struct prng * gen,double * array,int n)169 void prng_bfile_get_array(struct prng *gen,double *array,int n)
170 {
171 int i;
172
173 for(i=0;i<n;array[i++] = prng_bfile_get_next(gen));
174 }
175
176
177 /*
178 * prng_file_free: Free a File.
179 *
180 * Input:
181 * gen: Pointer to a struct prng.
182 *
183 */
prng_file_free(struct prng * gen)184 void prng_file_free(struct prng *gen)
185 {
186 fclose(gen->data.file_data.file);
187 prng_generic_free(gen);
188 }
189
190
191 /*
192 * Initialize ASCII File generator.
193 *
194 * Input:
195 * def: Pointer to struct prng_definition, as returned by
196 * prng_split_def.
197 *
198 * Returncode:
199 *
200 * struct prng * on success, NULL else
201 */
prng_afile_init(struct prng_definition * def)202 struct prng *prng_afile_init(struct prng_definition *def)
203 {
204 struct prng_file *g;
205 struct prng *gen;
206
207 if (strcasecmp("afile",def->type) != 0 ) /* hmm. type seems to be wrong. */
208 {
209 return(NULL);
210 }
211
212 if (def->num_parameters != 1) /* right number of parameters */
213 {
214 return(NULL);
215 }
216
217 gen = prng_allocate();
218 /*************************** Now prepare the generator itself */
219
220 g = &(gen->data.file_data);
221
222 strncpy(g->filename,def->parameter[0],PRNG_MAX_FILE_LEN-1);
223 g->file = fopen(g->filename,"r");
224
225 if(g->file == NULL) /* problems with the file ? */
226 {
227 perror("prng_afile_init");
228 free(gen);
229 return(NULL);
230 }
231
232 /*************************** fill in the generic struct. */
233
234 gen->reset = prng_file_reset;
235 gen->get_next = prng_afile_get_next;
236 gen->get_array = prng_afile_get_array;
237 gen->destroy = prng_file_free;
238
239 gen->is_congruential = FALSE;
240 gen->get_next_int = (prng_num (*)(struct prng *)) prng_undefined;
241 gen->modulus = 0;
242
243 gen->can_seed = FALSE;
244 gen->seed = (void (*)(struct prng *,prng_num seed)) prng_undefined;
245
246 gen->can_fast_sub = FALSE;
247 gen->get_sub_def = (char *(*)(struct prng *,prng_num s, prng_num i))
248 prng_undefined;
249 gen->can_fast_con = FALSE;
250 gen->get_con_def = (char *(*)(struct prng *,prng_num l, prng_num i))
251 prng_undefined;
252
253 gen->long_name = (char *) malloc(strlen(g->filename + 10));
254 if (gen->long_name != NULL)
255 {
256 strcpy(gen->long_name,"afile(");
257 strcat(gen->long_name,g->filename);
258 strcat(gen->long_name,")");
259 }
260
261 return(gen);
262 }
263
264
265 /*
266 * Initialize BINARY File generator.
267 *
268 * Input:
269 * def: Pointer to struct prng_definition, as returned by
270 * prng_split_def.
271 *
272 * Returncode:
273 *
274 * struct prng * on success, NULL else
275 */
prng_bfile_init(struct prng_definition * def)276 struct prng *prng_bfile_init(struct prng_definition *def)
277 {
278 struct prng_file *g;
279 struct prng *gen;
280
281 if (strcasecmp("bfile",def->type) != 0 ) /* hmm. type seems to be wrong. */
282 {
283 return(NULL);
284 }
285
286 if (def->num_parameters != 1) /* right number of parameters */
287 {
288 return(NULL);
289 }
290
291 gen = prng_allocate();
292 /*************************** Now prepare the generator itself */
293
294 g = &(gen->data.file_data);
295
296 strncpy(g->filename,def->parameter[0],PRNG_MAX_FILE_LEN-1);
297 g->file = fopen(g->filename,"r");
298
299 if(g->file == NULL) /* problems with the file ? */
300 {
301 perror("prng_bfile_init");
302 free(gen);
303 return(NULL);
304 }
305
306 /*************************** fill in the generic struct. */
307
308 gen->reset = prng_file_reset;
309 gen->get_next = prng_bfile_get_next;
310 gen->get_array = prng_bfile_get_array;
311 gen->destroy = prng_file_free;
312
313 gen->is_congruential = FALSE;
314 gen->get_next_int = (prng_num (*)(struct prng *)) prng_undefined;
315 gen->modulus = 0;
316
317 gen->can_seed = FALSE;
318 gen->seed = (void (*)(struct prng *,prng_num seed)) prng_undefined;
319
320 gen->can_fast_sub = FALSE;
321 gen->get_sub_def = (char *(*)(struct prng *,prng_num s, prng_num i))
322 prng_undefined;
323 gen->can_fast_con = FALSE;
324 gen->get_con_def = (char *(*)(struct prng *,prng_num l, prng_num i))
325 prng_undefined;
326
327
328 gen->long_name = (char *) malloc(strlen(g->filename + 10));
329 if (gen->long_name != NULL)
330 {
331 strcpy(gen->long_name,"bfile(");
332 strcat(gen->long_name,g->filename);
333 strcat(gen->long_name,")");
334 }
335
336 return(gen);
337 }
338
339