@ohos-ports/stdlib-random-base-minstd 0.0.0-stage → 0.2.3-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,99 @@
1
1
  {
2
2
  "name": "@ohos-ports/stdlib-random-base-minstd",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.3-beta.1",
4
+ "description": "A linear congruential pseudorandom number generator (LCG) based on Park and Miller.",
5
+ "license": "Apache-2.0",
6
+ "author": {
7
+ "name": "The Stdlib Authors",
8
+ "url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
9
+ },
10
+ "contributors": [
11
+ {
12
+ "name": "The Stdlib Authors",
13
+ "url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
14
+ }
15
+ ],
16
+ "main": "./lib",
17
+ "directories": {
18
+ "doc": "./docs",
19
+ "include": "./include",
20
+ "lib": "./lib",
21
+ "src": "./src",
22
+ "dist": "./dist"
23
+ },
24
+ "types": "./docs/types",
25
+ "scripts": {},
26
+ "homepage": "https://stdlib.io",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git://github.com/ohos-ports/ohos-ports.git",
30
+ "directory": "ports/stdlib/random-base-minstd/0.2.3"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/ohos-ports/ohos-ports/issues"
34
+ },
35
+ "dependencies": {
36
+ "@stdlib/array-int32": "^0.2.3",
37
+ "@ohos-ports/stdlib-array-to-json": "^0.3.1-beta.1",
38
+ "@ohos-ports/stdlib-assert-has-own-property": "^0.2.3-beta.2",
39
+ "@ohos-ports/stdlib-assert-is-boolean": "^0.2.3-beta.1",
40
+ "@ohos-ports/stdlib-assert-is-collection": "^0.2.3-beta.3",
41
+ "@stdlib/assert-is-int32array": "^0.2.3",
42
+ "@ohos-ports/stdlib-assert-is-plain-object": "^0.2.3-beta.2",
43
+ "@ohos-ports/stdlib-assert-is-positive-integer": "^0.2.3-beta.1",
44
+ "@ohos-ports/stdlib-blas-base-gcopy": "^0.2.3-beta.0",
45
+ "@stdlib/constants-int32-max": "^0.3.1",
46
+ "@ohos-ports/stdlib-math-base-special-floor": "^0.2.4-beta.1",
47
+ "@stdlib/random-base-shared": "^0.1.2",
48
+ "@ohos-ports/stdlib-string-format": "^0.2.3-beta.2",
49
+ "@ohos-ports/stdlib-utils-define-nonenumerable-read-only-accessor": "^0.2.4-beta.0",
50
+ "@ohos-ports/stdlib-utils-define-nonenumerable-read-only-property": "^0.2.3-beta.1",
51
+ "@ohos-ports/stdlib-utils-define-nonenumerable-read-write-accessor": "^0.2.3-beta.0",
52
+ "@ohos-ports/stdlib-error-tools-fmtprodmsg": "^0.2.3-beta.1"
53
+ },
54
+ "devDependencies": {},
55
+ "engines": {
56
+ "node": ">=0.10.0",
57
+ "npm": ">2.7.0"
58
+ },
59
+ "os": [
60
+ "aix",
61
+ "darwin",
62
+ "freebsd",
63
+ "linux",
64
+ "macos",
65
+ "openbsd",
66
+ "sunos",
67
+ "win32",
68
+ "windows",
69
+ "openharmony"
70
+ ],
71
+ "keywords": [
72
+ "stdlib",
73
+ "stdmath",
74
+ "mathematics",
75
+ "math",
76
+ "statistics",
77
+ "stats",
78
+ "prng",
79
+ "pseudorandom",
80
+ "random",
81
+ "rand",
82
+ "randint",
83
+ "randu",
84
+ "uniform",
85
+ "generator",
86
+ "lcg",
87
+ "minstd",
88
+ "lehmer",
89
+ "park",
90
+ "miller",
91
+ "park-miller",
92
+ "seed",
93
+ "seedable"
94
+ ],
95
+ "funding": {
96
+ "type": "opencollective",
97
+ "url": "https://opencollective.com/stdlib"
98
+ }
99
+ }
package/src/main.c ADDED
@@ -0,0 +1,430 @@
1
+ /**
2
+ * @license Apache-2.0
3
+ *
4
+ * Copyright (c) 2018 The Stdlib Authors.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #include "stdlib/random/base/minstd.h"
20
+ #include "stdlib/random/base/shared.h"
21
+ #include <stdlib.h>
22
+ #include <stdint.h>
23
+ #include <string.h>
24
+
25
+ // Forward declarations:
26
+ static inline int8_t next( struct BasePRNGObject *obj, uint64_t *out );
27
+ static inline int8_t normalized( struct BasePRNGObject *obj, double *out );
28
+ static inline void minstd_free( struct BasePRNGObject *obj );
29
+
30
+ // Define the LCG multiplier:
31
+ static const uint32_t A = 16807;
32
+
33
+ // Define the maximum signed 32-bit integer: 2147483647 => 0x7fffffff => 01111111111111111111111111111111
34
+ static const uint32_t MAX_INT32 = 0x7fffffff;
35
+
36
+ // Define the normalization constant:
37
+ static const double NORMALIZATION_CONSTANT = 2147483646.0; // MAX_INT32 - 1
38
+
39
+ /**
40
+ * MINSTD PRNG.
41
+ *
42
+ */
43
+ static const struct BasePRNG minstd_prng = {
44
+ "minstd", // name
45
+ (uint64_t)1, // min
46
+ (uint64_t)MAX_INT32-1, // max: (2^{31}-1) - 1
47
+ 0.0, // min (normalized)
48
+ (MAX_INT32-2) / NORMALIZATION_CONSTANT, // max (normalized): (MAX-1)/MAX
49
+ sizeof( stdlib_base_random_minstd_state_t ), // state_size
50
+ &next, // next()
51
+ &normalized, // normalized()
52
+ &minstd_free // free()
53
+ };
54
+
55
+ /**
56
+ * Returns a pseudorandom integer.
57
+ *
58
+ * ## Notes
59
+ *
60
+ * - The function returns `-1` if unable to generate a pseudorandom integer and `0` otherwise.
61
+ *
62
+ * @param obj PRNG object
63
+ * @param out output address
64
+ * @return status code
65
+ */
66
+ static inline int8_t next( struct BasePRNGObject *obj, uint64_t *out ) {
67
+ if ( obj == NULL || obj->prng != &minstd_prng ) {
68
+ return -1;
69
+ }
70
+ // Retrieve the state object:
71
+ stdlib_base_random_minstd_state_t *so = (stdlib_base_random_minstd_state_t *)( obj->state );
72
+
73
+ // Retrieve the current state:
74
+ uint32_t state = so->state;
75
+
76
+ // Explicitly cast to 64-bit to handle integer overflow:
77
+ state = (A*(uint64_t)state) % MAX_INT32;
78
+
79
+ // Update the PRNG state:
80
+ so->state = state;
81
+
82
+ // Set the output value:
83
+ *out = (uint64_t)state;
84
+
85
+ return 0;
86
+ }
87
+
88
+ /**
89
+ * Returns a pseudorandom double-precision floating-point number on the interval `[0,1)`.
90
+ *
91
+ * ## Notes
92
+ *
93
+ * - The function returns `-1` if unable to generate a pseudorandom number and `0` otherwise.
94
+ *
95
+ * @param obj PRNG object
96
+ * @param out output address
97
+ * @return status code
98
+ */
99
+ static inline int8_t normalized( struct BasePRNGObject *obj, double *out ) {
100
+ uint64_t state;
101
+ int8_t status = next( obj, &state );
102
+ if ( status != 0 ) {
103
+ return -1;
104
+ }
105
+ // Note: casting `state` to a double here is fine, as `state` will never exceed the maximum "safe" double-precision floating-point number:
106
+ *out = ((double)state-1.0) / NORMALIZATION_CONSTANT;
107
+
108
+ return 0;
109
+ }
110
+
111
+ /**
112
+ * Frees a PRNG's allocated memory.
113
+ *
114
+ * @param obj PRNG object
115
+ */
116
+ static inline void minstd_free( struct BasePRNGObject *obj ) {
117
+ if ( obj == NULL || obj->prng != &minstd_prng ) {
118
+ return;
119
+ }
120
+ free( obj->state );
121
+ free( obj );
122
+ }
123
+
124
+ /**
125
+ * Returns a pointer to a dynamically allocated PRNG.
126
+ *
127
+ * ## Notes
128
+ *
129
+ * - The user is responsible for freeing the allocated memory.
130
+ * - A provided `seed` is mapped to the interval `[1,2147483646]`.
131
+ *
132
+ * @param seed PRNG seed
133
+ * @return pointer to a dynamically allocated PRNG or, if unable to allocate memory, a null pointer
134
+ *
135
+ * @example
136
+ * #include "stdlib/random/base/minstd.h"
137
+ * #include "stdlib/random/base/shared.h"
138
+ * #include <stdlib.h>
139
+ * #include <stdio.h>
140
+ * #include <stdint.h>
141
+ *
142
+ * // Create a PRNG:
143
+ * struct BasePRNGObject *obj = stdlib_base_random_minstd_allocate( 12345 );
144
+ * if ( obj == NULL ) {
145
+ * fprintf( stderr, "Error allocating memory.\n" );
146
+ * exit( 1 );
147
+ * }
148
+ *
149
+ * uint64_t r;
150
+ * int8_t status = obj->prng->next( obj, &r );
151
+ * if ( status != 0 ) {
152
+ * fprintf( stderr, "Unexpected result.\n" );
153
+ * exit( 1 );
154
+ * }
155
+ *
156
+ * // ...
157
+ *
158
+ * status = obj->prng->next( obj, &r );
159
+ *
160
+ * // ...
161
+ *
162
+ * status = obj->prng->next( obj, &r );
163
+ *
164
+ * // ...
165
+ *
166
+ * // Free allocated memory:
167
+ * stdlib_base_random_minstd_free( obj );
168
+ */
169
+ struct BasePRNGObject * stdlib_base_random_minstd_allocate( const int32_t seed ) {
170
+ uint32_t iseed;
171
+
172
+ struct BasePRNGObject *obj = malloc( sizeof( struct BasePRNGObject ) );
173
+ if ( obj == NULL ) {
174
+ return NULL;
175
+ }
176
+ stdlib_base_random_minstd_state_t *state = malloc( sizeof( stdlib_base_random_minstd_state_t ) );
177
+ if ( state == NULL ) {
178
+ free( obj ); // prevent memory leaks
179
+ return NULL;
180
+ }
181
+ // Ensure that the provided seed is within allowed bounds...
182
+ if ( seed == 0 ) {
183
+ iseed = 1;
184
+ } else if ( seed == MAX_INT32 ) {
185
+ iseed = MAX_INT32 - 1;
186
+ } else if ( seed < 0 ) {
187
+ iseed = -seed;
188
+ } else {
189
+ iseed = seed;
190
+ }
191
+ state->seed = (uint32_t)iseed;
192
+ state->state = (uint32_t)iseed;
193
+
194
+ obj->prng = &minstd_prng;
195
+ obj->state = state;
196
+
197
+ return obj;
198
+ }
199
+
200
+ /**
201
+ * Frees a PRNG's allocated memory.
202
+ *
203
+ * @param obj PRNG object
204
+ *
205
+ * @example
206
+ * #include "stdlib/random/base/minstd.h"
207
+ * #include "stdlib/random/base/shared.h"
208
+ * #include <stdlib.h>
209
+ * #include <stdio.h>
210
+ * #include <stdint.h>
211
+ *
212
+ * // Create a PRNG:
213
+ * struct BasePRNGObject *obj = stdlib_base_random_minstd_allocate( 12345 );
214
+ * if ( obj == NULL ) {
215
+ * fprintf( stderr, "Error allocating memory.\n" );
216
+ * exit( 1 );
217
+ * }
218
+ *
219
+ * uint64_t r;
220
+ * int8_t status = obj->prng->next( obj, &r );
221
+ * if ( status != 0 ) {
222
+ * fprintf( stderr, "Unexpected result.\n" );
223
+ * exit( 1 );
224
+ * }
225
+ *
226
+ * // ...
227
+ *
228
+ * status = obj->prng->next( obj, &r );
229
+ *
230
+ * // ...
231
+ *
232
+ * status = obj->prng->next( obj, &r );
233
+ *
234
+ * // ...
235
+ *
236
+ * // Free allocated memory:
237
+ * stdlib_base_random_minstd_free( obj );
238
+ */
239
+ void stdlib_base_random_minstd_free( struct BasePRNGObject *obj ) {
240
+ if ( obj == NULL || obj->prng != &minstd_prng ) {
241
+ return;
242
+ }
243
+ obj->prng->free( obj );
244
+ }
245
+
246
+ /**
247
+ * Returns a PRNG seed.
248
+ *
249
+ * ## Notes
250
+ *
251
+ * - The function returns `-1` if unable to resolve a PRNG seed and `0` otherwise.
252
+ *
253
+ * @param obj PRNG object
254
+ * @param out output address
255
+ * @return status code
256
+ *
257
+ * @example
258
+ * #include "stdlib/random/base/minstd.h"
259
+ * #include "stdlib/random/base/shared.h"
260
+ * #include <stdlib.h>
261
+ * #include <stdio.h>
262
+ * #include <stdint.h>
263
+ *
264
+ * // Create a PRNG:
265
+ * struct BasePRNGObject *obj = stdlib_base_random_minstd_allocate( 12345 );
266
+ * if ( obj == NULL ) {
267
+ * fprintf( stderr, "Error allocating memory.\n" );
268
+ * exit( 1 );
269
+ * }
270
+ *
271
+ * int32_t seed;
272
+ * int8_t status = stdlib_base_random_minstd_seed( obj, &seed );
273
+ * if ( status != 0 ) {
274
+ * fprintf( stderr, "Error encountered when attempting to retrieve the PRNG seed.\n" );
275
+ * exit( 1 );
276
+ * }
277
+ *
278
+ * // Use the seed to, e.g., create another PRNG which will generate the same sequence...
279
+ *
280
+ * // Free allocated memory:
281
+ * stdlib_base_random_minstd_free( obj );
282
+ */
283
+ int8_t stdlib_base_random_minstd_seed( const struct BasePRNGObject *obj, int32_t *out ) {
284
+ if ( obj == NULL || obj->prng != &minstd_prng ) {
285
+ return -1;
286
+ }
287
+ // Retrieve the MINSTD state object:
288
+ const stdlib_base_random_minstd_state_t *state = (stdlib_base_random_minstd_state_t *)( obj->state );
289
+
290
+ // Set the output value:
291
+ *out = (int32_t)( state->seed );
292
+
293
+ return 0;
294
+ }
295
+
296
+ /**
297
+ * Returns a **copy** of the current PRNG state.
298
+ *
299
+ * ## Notes
300
+ *
301
+ * - The user is responsible for freeing the allocated memory.
302
+ *
303
+ * @param obj PRNG object
304
+ * @return pointer to a copy of the PRNG's internal state or, if unable to allocate memory, a null pointer
305
+ *
306
+ * @example
307
+ * #include "stdlib/random/base/minstd.h"
308
+ * #include "stdlib/random/base/shared.h"
309
+ * #include <stdlib.h>
310
+ * #include <stdio.h>
311
+ * #include <stdint.h>
312
+ *
313
+ * // Create a PRNG:
314
+ * struct BasePRNGObject *obj = stdlib_base_random_minstd_allocate( 12345 );
315
+ * if ( obj == NULL ) {
316
+ * fprintf( stderr, "Error allocating memory.\n" );
317
+ * exit( 1 );
318
+ * }
319
+ *
320
+ * void *state = stdlib_base_random_minstd_state( obj );
321
+ * if ( state == NULL ) {
322
+ * fprintf( stderr, "Unable to retrieve PRNG state.\n" );
323
+ * exit( 1 );
324
+ * }
325
+ *
326
+ * // Use the captured state to, e.g., sync another PRNG or to reset a PRNG to a particular state in order to "replay" generated values at a later point in time...
327
+ *
328
+ * // Free allocated memory:
329
+ * stdlib_base_random_minstd_free( obj );
330
+ * free( state );
331
+ */
332
+ void * stdlib_base_random_minstd_state( const struct BasePRNGObject *obj ) {
333
+ if ( obj == NULL || obj->prng != &minstd_prng ) {
334
+ return NULL;
335
+ }
336
+ void *state = malloc( obj->prng->state_size );
337
+ if ( state == NULL ) {
338
+ return NULL;
339
+ }
340
+ memcpy( state, obj->state, obj->prng->state_size );
341
+ return state;
342
+ }
343
+
344
+ /**
345
+ * Sets the PRNG state.
346
+ *
347
+ * ## Notes
348
+ *
349
+ * - The function returns `-1` if unable to set a PRNG state and `0` otherwise.
350
+ *
351
+ * @param obj PRNG object
352
+ * @param state state
353
+ * @return status code
354
+ *
355
+ * @example
356
+ * #include "stdlib/random/base/minstd.h"
357
+ * #include "stdlib/random/base/shared.h"
358
+ * #include <stdlib.h>
359
+ * #include <stdio.h>
360
+ * #include <stdint.h>
361
+ *
362
+ * // Create a PRNG:
363
+ * struct BasePRNGObject *obj = stdlib_base_random_minstd_allocate( 12345 );
364
+ * if ( obj == NULL ) {
365
+ * fprintf( stderr, "Error allocating memory.\n" );
366
+ * exit( 1 );
367
+ * }
368
+ *
369
+ * uint64_t r;
370
+ * int8_t status = obj->prng->next( obj, &r );
371
+ * if ( status != 0 ) {
372
+ * fprintf( stderr, "Unexpected result.\n" );
373
+ * exit( 1 );
374
+ * }
375
+ *
376
+ * // ...
377
+ *
378
+ * status = obj->prng->next( obj, &r );
379
+ *
380
+ * // ...
381
+ *
382
+ * status = obj->prng->next( obj, &r );
383
+ *
384
+ * // ...
385
+ *
386
+ * // Retrieve the current PRNG state...
387
+ * void *state = stdlib_base_random_minstd_state( obj );
388
+ * if ( state == NULL ) {
389
+ * fprintf( stderr, "Error encountered when attempting to retrieve PRNG state.\n" );
390
+ * exit( 1 );
391
+ * }
392
+ *
393
+ * // ...
394
+ *
395
+ * status = obj->prng->next( obj, &r );
396
+ *
397
+ * // ...
398
+ *
399
+ * status = obj->prng->next( obj, &r );
400
+ *
401
+ * // ...
402
+ *
403
+ * // Reset the PRNG to a previous state...
404
+ * status = stdlib_base_random_minstd_set( obj, state );
405
+ * if ( status != 0 ) {
406
+ * fprintf( stderr, "Error encountered when attempting to set PRNG state.\n" );
407
+ * exit( 1 );
408
+ * }
409
+ *
410
+ * // ...
411
+ *
412
+ * status = obj->prng->next( obj, &r );
413
+ *
414
+ * // ...
415
+ *
416
+ * status = obj->prng->next( obj, &r );
417
+ *
418
+ * // ...
419
+ *
420
+ * // Free allocated memory:
421
+ * stdlib_base_random_minstd_free( obj );
422
+ * free( state );
423
+ */
424
+ int8_t stdlib_base_random_minstd_set( struct BasePRNGObject *obj, const void *state ) {
425
+ if ( obj == NULL || state == NULL || obj->prng != &minstd_prng ) {
426
+ return -1;
427
+ }
428
+ memcpy( obj->state, state, obj->prng->state_size );
429
+ return 0;
430
+ }