/** * @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 #include "stdlib/random/base.h" /** * Frees a PRNG's allocated memory. * * @param obj PRNG object */ void stdlib_base_prng_free( struct BasePRNGObject *obj ) { if ( obj == NULL ) { return; } obj->prng->free( obj ); } /** * Returns a pseudorandom integer. * * ## Notes * * - The function returns `0` if provided a `NULL` pointer. * * @param obj PRNG object * @return pseudorandom integer */ uint64_t stdlib_base_prng_next( struct BasePRNGObject *obj ) { if ( obj == NULL ) { return 0; } uint64_t v; obj->prng->next( obj, &v ); return v; } /** * 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 */ double stdlib_base_prng_normalized( struct BasePRNGObject *obj ) { if ( obj == NULL ) { return NAN; } double v; obj->prng->normalized( obj, &v ); return v; } /** * Returns a PRNG name. * * @param obj PRNG object * @return PRNG name */ const char * stdlib_base_prng_name( const struct BasePRNGObject *obj ) { return obj->prng->name; } /** * Returns the minimum possible integer value generated by a provided PRNG. * * @param obj PRNG object * @return minimum possible integer value */ uint64_t stdlib_base_prng_min( const struct BasePRNGObject *obj ) { return (uint64_t)( obj->prng->min ); } /** * Returns the maximum possible integer value generated by a provided PRNG. * * @param obj PRNG object * @return maximum possible integer value */ uint64_t stdlib_base_prng_max( const struct BasePRNGObject *obj ) { return (uint64_t)( obj->prng->max ); } /** * Returns the minimum possible double-precision floating-point number generated by a provided PRNG. * * @param obj PRNG object * @return minimum possible double */ double stdlib_base_prng_normalized_min( const struct BasePRNGObject *obj ) { return (double)( obj->prng->normalized_min ); } /** * Returns the maximum possible double-precision floating-point number generated by a provided PRNG. * * @param obj PRNG object * @return maximum possible double */ double stdlib_base_prng_normalized_max( const struct BasePRNGObject *obj ) { return (double)( obj->prng->normalized_max ); } /** * Returns the size of a provided PRNG's internal state. * * @param obj PRNG object * @return state size */ size_t stdlib_base_prng_state_size( const struct BasePRNGObject *obj ) { return (size_t)( obj->prng->state_size ); } /** * Returns a copy of a PRNG's internal state. * * ## Notes * * - The user is responsible for freeing the allocated memory. * * @param obj PRNG object * @return pointer to a copy of a PRNG's internal state or, if unable to allocate memory, a null pointer */ void * stdlib_base_prng_state( const struct BasePRNGObject *obj ) { if ( obj == NULL ) { return NULL; } void *state = malloc( obj->prng->state_size ); if ( state == NULL ) { return NULL; } memcpy( state, obj->state, obj->prng->state_size ); return state; } /** * Sets a PRNG's state. * * ## Notes * * - The function returns `-1` if unable to set a PRNG state and `0` otherwise. * * @param obj PRNG object * @param state state * @return status code */ int8_t stdlib_base_prng_set( struct BasePRNGObject *obj, const void *vstate ) { if ( obj == NULL || vstate == NULL ) { return -1; } memcpy( obj->state, vstate, obj->prng->state_size ); return 0; } /** * Copies a PRNG. * * @param src source PRNG object * @return pointer to a dynamically allocated PRNG or, if unable to allocate memory, a null pointer */ struct BasePRNGObject * stdlib_base_prng_copy( const struct BasePRNGObject *src ) { struct BasePRNGObject *out = (struct BasePRNGObject *)malloc( sizeof( struct BasePRNGObject ) ); if ( out == NULL ) { return NULL; } // Allocate memory for the PRNG state... out->state = malloc( src->prng->state_size ); if ( out->state == NULL ) { free( out ); // prevent memory leaks return NULL; } // Set the PRNG (includes PRNG properties and methods): out->prng = src->prng; // Copy the current source PRNG state: memcpy( out->state, src->state, src->prng->state_size ); return out; } /** * Copies a PRNG state from a source PRNG to a destination PRNG of the same kind. * * ## Notes * * - The function returns `-1` if unable to copy a PRNG's state and `0` otherwise. * * @param dest destination PRNG object * @param src source PRNG object * @return status code */ int8_t stdlib_base_prng_copy_state( struct BasePRNGObject *dest, const struct BasePRNGObject *src ) { // We can only copy state between compatible PRNGs... if ( dest->prng != src->prng ) { return -1; } // Copy the current source PRNG state: memcpy( dest->state, src->state, src->prng->state_size ); return 0; }