main.c (5013B)
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 // Note: keep project includes in alphabetical order... 20 #include <stdlib.h> 21 #include <stdint.h> 22 #include <stdarg.h> 23 #include "stdlib/random/base.h" 24 #include "stdlib/random/base/minstd.h" 25 #include "stdlib/random/base/minstd_shuffle.h" 26 #include "stdlib/random/base/mt19937.h" 27 #include "stdlib/random/base/randi.h" 28 29 // Define the default PRNG: 30 static const enum STDLIB_BASE_RANDOM_RANDI_PRNG STDLIB_BASE_RANDOM_RANDI_DEFAULT = STDLIB_BASE_RANDOM_RANDI_MT19937; 31 32 /** 33 * Returns a pointer to a dynamically allocated PRNG. 34 * 35 * ## Notes 36 * 37 * - The user is responsible for freeing the allocated memory. 38 * 39 * @param nargs number of provided optional arguments 40 * @param [prng] PRNG to allocate 41 * @param [seed] PRNG seed 42 * @param [len] seed array length 43 * @return pointer to a dynamically allocated PRNG or, if unable to allocate memory, a null pointer 44 * 45 * @example 46 * #include <stdlib.h> 47 * #include <stdio.h> 48 * #include <stdint.h> 49 * #include "stdlib/random/base.h" 50 * #include "stdlib/random/base/randi.h" 51 * 52 * // Create a PRNG: 53 * struct BasePRNGObject *obj = stdlib_base_random_randi_allocate( 0 ); 54 * if ( obj == NULL ) { 55 * fprintf( stderr, "Error allocating PRNG.\n" ); 56 * exit( 1 ); 57 * } 58 * 59 * uint64_t r = stdlib_base_random_randi( obj ); 60 * 61 * // ... 62 * 63 * r = stdlib_base_random_randi( obj ); 64 * 65 * // ... 66 * 67 * r = stdlib_base_random_randi( obj ); 68 * 69 * // ... 70 * 71 * // Free allocated memory: 72 * stdlib_base_random_randi_free( obj ); 73 */ 74 struct BasePRNGObject * stdlib_base_random_randi_allocate( const int nargs, ... ) { 75 enum STDLIB_BASE_RANDOM_RANDI_PRNG prng; 76 struct BasePRNGObject *obj; 77 78 va_list args; 79 va_start( args, nargs ); 80 81 if ( nargs < 1 ) { 82 prng = STDLIB_BASE_RANDOM_RANDI_DEFAULT; 83 } else { 84 prng = va_arg( args, enum STDLIB_BASE_RANDOM_RANDI_PRNG ); 85 } 86 if ( prng == STDLIB_BASE_RANDOM_RANDI_MINSTD ) { 87 int32_t seed; 88 if ( nargs > 1 ) { 89 seed = va_arg( args, int32_t ); 90 } else { 91 seed = rand(); 92 } 93 obj = stdlib_base_random_minstd_allocate( seed ); 94 } else if ( prng == STDLIB_BASE_RANDOM_RANDI_MINSTD_SHUFFLE ) { 95 int32_t seed; 96 if ( nargs > 1 ) { 97 seed = va_arg( args, int32_t ); 98 } else { 99 seed = rand(); 100 } 101 obj = stdlib_base_random_minstd_shuffle_allocate( seed ); 102 } else if ( prng == STDLIB_BASE_RANDOM_RANDI_MT19937 ) { 103 int64_t seed_length; 104 uint32_t *seed; 105 if ( nargs < 2 ) { 106 uint32_t tseed[] = { (uint32_t)rand() }; 107 seed = tseed; 108 seed_length = 1; 109 } else if ( nargs == 3 ) { 110 seed = va_arg( args, uint32_t * ); 111 seed_length = va_arg( args, int64_t ); 112 } else { 113 // Incompatible number of arguments... 114 va_end( args ); 115 return NULL; 116 } 117 obj = stdlib_base_random_mt19937_allocate( seed, seed_length ); 118 } else { 119 // How did we get here? A non-implemented PRNG? 120 obj = NULL; 121 } 122 va_end( args ); 123 return obj; 124 } 125 126 /** 127 * Returns a pseudorandom integer. 128 * 129 * ## Notes 130 * 131 * - The function returns `0` if provided a `NULL` pointer. 132 * 133 * @param obj PRNG object 134 * @return pseudorandom integer 135 * 136 * @example 137 * #include <stdlib.h> 138 * #include <stdio.h> 139 * #include <stdint.h> 140 * #include "stdlib/random/base.h" 141 * #include "stdlib/random/base/randi.h" 142 * 143 * // Create a PRNG: 144 * struct BasePRNGObject *obj = stdlib_base_random_randi_allocate( 0 ); 145 * if ( obj == NULL ) { 146 * fprintf( stderr, "Error allocating PRNG.\n" ); 147 * exit( 1 ); 148 * } 149 * 150 * uint64_t r = stdlib_base_random_randi( obj ); 151 * 152 * // ... 153 * 154 * r = stdlib_base_random_randi( obj ); 155 * 156 * // ... 157 * 158 * r = stdlib_base_random_randi( obj ); 159 * 160 * // ... 161 * 162 * // Free allocated memory: 163 * stdlib_base_random_randi_free( obj ); 164 */ 165 uint64_t stdlib_base_random_randi( struct BasePRNGObject *obj ) { 166 return stdlib_base_prng_next( obj ); 167 } 168 169 /** 170 * Frees a PRNG's allocated memory. 171 * 172 * @param obj PRNG object 173 * 174 * @example 175 * #include <stdlib.h> 176 * #include <stdio.h> 177 * #include <stdint.h> 178 * #include "stdlib/random/base.h" 179 * #include "stdlib/random/base/randi.h" 180 * 181 * // Create a PRNG: 182 * struct BasePRNGObject *obj = stdlib_base_random_randi_allocate( 0 ); 183 * if ( obj == NULL ) { 184 * fprintf( stderr, "Error allocating PRNG.\n" ); 185 * exit( 1 ); 186 * } 187 * 188 * uint64_t r = stdlib_base_random_randi( obj ); 189 * 190 * // ... 191 * 192 * r = stdlib_base_random_randi( obj ); 193 * 194 * // ... 195 * 196 * r = stdlib_base_random_randi( obj ); 197 * 198 * // ... 199 * 200 * // Free allocated memory: 201 * stdlib_base_random_randi_free( obj ); 202 */ 203 void stdlib_base_random_randi_free( struct BasePRNGObject *obj ) { 204 stdlib_base_prng_free( obj ); 205 }