224 lines
5.4 KiB
C
224 lines
5.4 KiB
C
/**
|
|
* @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 <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#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;
|
|
}
|