99 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			99 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#pragma once
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <kinc/global.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*! \file random.h
							 | 
						||
| 
								 | 
							
								    \brief Generates values which are kind of random.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __cplusplus
							 | 
						||
| 
								 | 
							
								extern "C" {
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// Initializes the randomizer with a seed. This is optional but helpful.
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <param name="seed">A value which should ideally be pretty random</param>
							 | 
						||
| 
								 | 
							
								KINC_FUNC void kinc_random_init(int64_t seed);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// Returns a random value.
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <returns>A random value</returns>
							 | 
						||
| 
								 | 
							
								KINC_FUNC int64_t kinc_random_get(void);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// Returns a value between 0 and max (both inclusive).
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <returns>A random value</returns>
							 | 
						||
| 
								 | 
							
								KINC_FUNC int64_t kinc_random_get_max(int64_t max);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// <summary>
							 | 
						||
| 
								 | 
							
								/// Returns a value between min and max (both inclusive).
							 | 
						||
| 
								 | 
							
								/// </summary>
							 | 
						||
| 
								 | 
							
								/// <returns>A random value</returns>
							 | 
						||
| 
								 | 
							
								KINC_FUNC int64_t kinc_random_get_in(int64_t min, int64_t max);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_IMPLEMENTATION_MATH
							 | 
						||
| 
								 | 
							
								#define KINC_IMPLEMENTATION
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_IMPLEMENTATION
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <limits.h>
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// xoshiro256** 1.0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static inline uint64_t rotl(const uint64_t x, int k) {
							 | 
						||
| 
								 | 
							
									return (x << k) | (x >> (64 - k));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static uint64_t s[4] = {1, 2, 3, 4};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint64_t next(void) {
							 | 
						||
| 
								 | 
							
									const uint64_t result = rotl(s[1] * 5, 7) * 9;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const uint64_t t = s[1] << 17;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									s[2] ^= s[0];
							 | 
						||
| 
								 | 
							
									s[3] ^= s[1];
							 | 
						||
| 
								 | 
							
									s[1] ^= s[2];
							 | 
						||
| 
								 | 
							
									s[0] ^= s[3];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									s[2] ^= t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									s[3] = rotl(s[3], 45);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_random_init(int64_t seed) {
							 | 
						||
| 
								 | 
							
									s[0] = (uint64_t)seed;
							 | 
						||
| 
								 | 
							
									s[1] = 2;
							 | 
						||
| 
								 | 
							
									s[2] = 3;
							 | 
						||
| 
								 | 
							
									s[3] = 4;
							 | 
						||
| 
								 | 
							
									s[1] = next();
							 | 
						||
| 
								 | 
							
									s[2] = next();
							 | 
						||
| 
								 | 
							
									s[3] = next();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int64_t kinc_random_get(void) {
							 | 
						||
| 
								 | 
							
									return (int64_t)next();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int64_t kinc_random_get_max(int64_t max) {
							 | 
						||
| 
								 | 
							
									return kinc_random_get() % (max + 1);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int64_t kinc_random_get_in(int64_t min, int64_t max) {
							 | 
						||
| 
								 | 
							
									int64_t value = kinc_random_get();
							 | 
						||
| 
								 | 
							
									return (value < -LLONG_MAX ? LLONG_MAX : llabs(value)) % (max + 1 - min) + min;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __cplusplus
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 |