<commit_before>/**
* @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 "stdlib/random/base.h"
#include "stdlib/random/base/minstd.h"

// Define the LCG multiplier:
static const uint32_t A = 16807;

// Define the maximum signed 32-bit integer: 2147483647 => 0x7fffffff => 01111111111111111111111111111111
static const uint32_t MAX_INT32 = 0x7fffffff;

// Define the normalization constant:
static const double NORMALIZATION_CONSTANT = 2147483646.0; // MAX_INT32 - 1

/**
* Returns a pseudorandom integer.
*
* @private
* @param vstate  PRNG state
* @return        pseudorandom integer
*/
static inline uint64_t next( void *vstate ) {
	// Cast the "void state" argument to a MINSTD state object:
	stdlib_base_minstd_prng_state_t *obj = (stdlib_base_minstd_prng_state_t *)( vstate );

	// Retrieve the current state:
	uint32_t state = obj->state;

	// Explicitly cast to 64-bit to handle integer overflow:
	state = (A*(uint64_t)state) % MAX_INT32;

	// Update the PRNG state:
	obj->state = state;

	// Return the generated value:
	return (uint64_t)state;
}

/**
* Returns a pseudorandom double-precision floating-point number on the interval `[0,1)`.
*
* @private
* @param vstate  PRNG state
* @return        pseudorandom number
*/
static inline double normalized( void *vstate ) {
	double state = (double)next( vstate );
	return (state-1.0) / NORMALIZATION_CONSTANT;
}

/**
* MINSTD PRNG.
*
* @private
*/
static const struct BasePRNG minstd_prng = {
	"minstd",                                   // name
	(uint64_t)1,                                // min
	(uint64_t)MAX_INT32-1,                      // max: (2^{31}-1) - 1
	0.0,                                        // min (normalized)
	(MAX_INT32-2) / NORMALIZATION_CONSTANT,     // max (normalized): (MIN-1)/MAX
	sizeof( stdlib_base_minstd_prng_state_t ),  // state_size
	&next,                                      // next()
	&normalized                                 // normalized()
};

/**
* Returns a pointer to a dynamically allocated MINSTD PRNG.
*
* ## Notes
*
* -   The user is responsible for freeing the allocated memory.
*
* @param seed  PRNG seed
* @return      pointer to a dynamically allocated PRNG or, if unable to allocate memory, a null pointer
*
* @example
* #include <stdlib.h>
* #include <stdio.h>
* #include <stdint.h>
* #include "stdlib/random/base.h"
* #include "stdlib/random/base/minstd.h"
*
* // Create a MINSTD PRNG:
* struct BasePRNGObject *obj = stdlib_base_minstd_prng_allocate( 12345 );
* if ( obj == NULL ) {
*     fprintf( stderr, "Error allocating memory.\n" );
*     exit( 1 );
* }
*
* uint64_t r = obj->prng->next( obj->state );
*
* // ...
*
* r = obj->prng->next( obj->state );
* r = obj->prng->next( obj->state );
*
* // ...
*
* // Free allocated memory:
* stdlib_base_minstd_prng_free( obj );
*/
struct BasePRNGObject * stdlib_base_minstd_prng_allocate( const int32_t seed ) {
	struct BasePRNGObject *obj = malloc( sizeof( struct BasePRNGObject ) );
	if ( obj == NULL ) {
		return NULL;
	}
	stdlib_base_minstd_prng_state_t *state = malloc( sizeof( stdlib_base_minstd_prng_state_t ) );
	if ( state == NULL ) {
		free( obj ); // prevent memory leaks
		return NULL;
	}
	state->seed = (uint32_t)seed;
	state->state = (uint32_t)seed;

	obj->prng = &minstd_prng;
	obj->state = state;

	return obj;
}

/**
* Frees a MINSTD PRNG's allocated memory.
*
* @param obj  PRNG object
*
* @example
* #include <stdlib.h>
* #include <stdio.h>
* #include <stdint.h>
* #include "stdlib/random/base.h"
* #include "stdlib/random/base/minstd.h"
*
* // Create a MINSTD PRNG:<commit_msg>Ensure provided seed is within allowed bounds<commit_after>/**
* @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 "stdlib/random/base.h"
#include "stdlib/random/base/minstd.h"

// Define the LCG multiplier:
static const uint32_t A = 16807;

// Define the maximum signed 32-bit integer: 2147483647 => 0x7fffffff => 01111111111111111111111111111111
static const uint32_t MAX_INT32 = 0x7fffffff;

// Define the normalization constant:
static const double NORMALIZATION_CONSTANT = 2147483646.0; // MAX_INT32 - 1

/**
* Returns a pseudorandom integer.
*
* @private
* @param vstate  PRNG state
* @return        pseudorandom integer
*/
static inline uint64_t next( void *vstate ) {
	// Cast the "void state" argument to a MINSTD state object:
	stdlib_base_minstd_prng_state_t *obj = (stdlib_base_minstd_prng_state_t *)( vstate );

	// Retrieve the current state:
	uint32_t state = obj->state;

	// Explicitly cast to 64-bit to handle integer overflow:
	state = (A*(uint64_t)state) % MAX_INT32;

	// Update the PRNG state:
	obj->state = state;

	// Return the generated value:
	return (uint64_t)state;
}

/**
* Returns a pseudorandom double-precision floating-point number on the interval `[0,1)`.
*
* @private
* @param vstate  PRNG state
* @return        pseudorandom number
*/
static inline double normalized( void *vstate ) {
	double state = (double)next( vstate );
	return (state-1.0) / NORMALIZATION_CONSTANT;
}

/**
* MINSTD PRNG.
*
* @private
*/
static const struct BasePRNG minstd_prng = {
	"minstd",                                   // name
	(uint64_t)1,                                // min
	(uint64_t)MAX_INT32-1,                      // max: (2^{31}-1) - 1
	0.0,                                        // min (normalized)
	(MAX_INT32-2) / NORMALIZATION_CONSTANT,     // max (normalized): (MIN-1)/MAX
	sizeof( stdlib_base_minstd_prng_state_t ),  // state_size
	&next,                                      // next()
	&normalized                                 // normalized()
};

/**
* Returns a pointer to a dynamically allocated MINSTD PRNG.
*
* ## Notes
*
* -   The user is responsible for freeing the allocated memory.
*
* @param seed  PRNG seed
* @return      pointer to a dynamically allocated PRNG or, if unable to allocate memory, a null pointer
*
* @example
* #include <stdlib.h>
* #include <stdio.h>
* #include <stdint.h>
* #include "stdlib/random/base.h"
* #include "stdlib/random/base/minstd.h"
*
* // Create a MINSTD PRNG:
* struct BasePRNGObject *obj = stdlib_base_minstd_prng_allocate( 12345 );
* if ( obj == NULL ) {
*     fprintf( stderr, "Error allocating memory.\n" );
*     exit( 1 );
* }
*
* uint64_t r = obj->prng->next( obj->state );
*
* // ...
*
* r = obj->prng->next( obj->state );
* r = obj->prng->next( obj->state );
*
* // ...
*
* // Free allocated memory:
* stdlib_base_minstd_prng_free( obj );
*/
struct BasePRNGObject * stdlib_base_minstd_prng_allocate( const int32_t seed ) {
	uint32_t iseed;

	struct BasePRNGObject *obj = malloc( sizeof( struct BasePRNGObject ) );
	if ( obj == NULL ) {
		return NULL;
	}
	stdlib_base_minstd_prng_state_t *state = malloc( sizeof( stdlib_base_minstd_prng_state_t ) );
	if ( state == NULL ) {
		free( obj ); // prevent memory leaks
		return NULL;
	}
	// Ensure that the provided seed is within allowed bounds...
	if ( seed == 0 ) {
		iseed = 1;
	} else if ( seed == MAX_INT32 ) {
		iseed = MAX_INT32 - 1;
	} else {
		iseed = (uint32_t)seed;
	}
	state->seed = iseed;
	state->state = iseed;

	obj->prng = &minstd_prng;
	obj->state = state;

	return obj;
}

/**
* Frees a MINSTD PRNG's allocated memory.
*
* @param obj  PRNG object
*
* @example
* #include <stdlib.h>
* #include <stdio.h>
* #include <stdint.h>
* #include "stdlib/random/base.h"
* #include "stdlib/random/base/minstd.h"
*
* // Create a MINSTD PRNG:
{'fraction_non_alphanumeric': 0.125947187141217, 'fraction_numerical': 0.03111366245694604, 'mean_word_length': 3.072463768115942, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6341566', 'n_tokens_mistral': 3152, 'n_tokens_neox': 2916, 'n_words': 859}