/** * @license Apache-2.0 * * Copyright (c) 2018 The Stdlib Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // Note: keep project includes in alphabetical order... #include #include #include #include "stdlib/random/base.h" #include "stdlib/random/base/minstd.h" #include "stdlib/random/base/minstd_shuffle.h" #include "stdlib/random/base/mt19937.h" #include "stdlib/random/base/randu.h" // Define the default PRNG: static const enum STDLIB_BASE_RANDOM_RANDU_PRNG STDLIB_BASE_RANDOM_RANDU_DEFAULT = STDLIB_BASE_RANDOM_RANDU_MT19937; /** * Returns a pointer to a dynamically allocated PRNG. * * ## Notes * * - The user is responsible for freeing the allocated memory. * * @param nargs number of provided optional arguments * @param [prng] PRNG to allocate * @param [seed] PRNG seed * @param [len] seed array length * @return pointer to a dynamically allocated PRNG or, if unable to allocate memory, a null pointer * * @example * #include * #include * #include * #include "stdlib/random/base.h" * #include "stdlib/random/base/randu.h" * * // Create a PRNG: * struct BasePRNGObject *obj = stdlib_base_random_randu_allocate( 0 ); * if ( obj == NULL ) { * fprintf( stderr, "Error allocating PRNG.\n" ); * exit( 1 ); * } * * double r = stdlib_base_random_randu( obj ); * * // ... * * r = stdlib_base_random_randu( obj ); * * // ... * * r = stdlib_base_random_randu( obj ); * * // ... * * // Free allocated memory: * stdlib_base_random_randu_free( obj ); */ struct BasePRNGObject * stdlib_base_random_randu_allocate( const int nargs, ... ) { enum STDLIB_BASE_RANDOM_RANDU_PRNG prng; struct BasePRNGObject *obj; va_list args; va_start( args, nargs ); if ( nargs < 1 ) { prng = STDLIB_BASE_RANDOM_RANDU_DEFAULT; } else { prng = va_arg( args, enum STDLIB_BASE_RANDOM_RANDU_PRNG ); } if ( prng == STDLIB_BASE_RANDOM_RANDU_MINSTD ) { int32_t seed; if ( nargs > 1 ) { seed = va_arg( args, int32_t ); } else { seed = rand(); } obj = stdlib_base_random_minstd_allocate( seed ); } else if ( prng == STDLIB_BASE_RANDOM_RANDU_MINSTD_SHUFFLE ) { int32_t seed; if ( nargs > 1 ) { seed = va_arg( args, int32_t ); } else { seed = rand(); } obj = stdlib_base_random_minstd_shuffle_allocate( seed ); } else if ( prng == STDLIB_BASE_RANDOM_RANDU_MT19937 ) { int64_t seed_length; uint32_t *seed; if ( nargs < 2 ) { uint32_t tseed[] = { (uint32_t)rand() }; seed = tseed; seed_length = 1; } else if ( nargs == 3 ) { seed = va_arg( args, uint32_t * ); seed_length = va_arg( args, int64_t ); } else { // Incompatible number of arguments... va_end( args ); return NULL; } obj = stdlib_base_random_mt19937_allocate( seed, seed_length ); } else { // How did we get here? A non-implemented PRNG? obj = NULL; } va_end( args ); return obj; } /** * Returns a pseudorandom double-precision floating-point number on the interval `[0,1)`. * * ## Notes * * - The function returns `NAN` if provided a `NULL` pointer. * * @param obj PRNG object * @return pseudorandom number * * @example * #include * #include * #include * #include "stdlib/random/base.h" * #include "stdlib/random/base/randu.h" * * // Create a PRNG: * struct BasePRNGObject *obj = stdlib_base_random_randu_allocate( 0 ); * if ( obj == NULL ) { * fprintf( stderr, "Error allocating PRNG.\n" ); * exit( 1 ); * } * * double r = stdlib_base_random_randu( obj ); * * // ... * * r = stdlib_base_random_randu( obj ); * * // ... * * r = stdlib_base_random_randu( obj ); * * // ... * * // Free allocated memory: * stdlib_base_random_randu_free( obj ); */ double stdlib_base_random_randu( struct BasePRNGObject *obj ) { return stdlib_base_prng_normalized( obj ); } /** * Frees a PRNG's allocated memory. * * @param obj PRNG object * * @example * #include * #include * #include * #include "stdlib/random/base.h" * #include "stdlib/random/base/randu.h" * * // Create a PRNG: * struct BasePRNGObject *obj = stdlib_base_random_randu_allocate( 0 ); * if ( obj == NULL ) { * fprintf( stderr, "Error allocating PRNG.\n" ); * exit( 1 ); * } * * double r = stdlib_base_random_randu( obj ); * * // ... * * r = stdlib_base_random_randu( obj ); * * // ... * * r = stdlib_base_random_randu( obj ); * * // ... * * // Free allocated memory: * stdlib_base_random_randu_free( obj ); */ void stdlib_base_random_randu_free( struct BasePRNGObject *obj ) { stdlib_base_prng_free( obj ); }