1bbbf1280Sopenharmony_ci/* 2bbbf1280Sopenharmony_ci * random.c - random number generator for producing mathlib test cases 3bbbf1280Sopenharmony_ci * 4bbbf1280Sopenharmony_ci * Copyright (c) 1998-2019, Arm Limited. 5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT 6bbbf1280Sopenharmony_ci */ 7bbbf1280Sopenharmony_ci 8bbbf1280Sopenharmony_ci#include "types.h" 9bbbf1280Sopenharmony_ci#include "random.h" 10bbbf1280Sopenharmony_ci 11bbbf1280Sopenharmony_cistatic uint32 seedbuf[55]; 12bbbf1280Sopenharmony_cistatic int seedptr; 13bbbf1280Sopenharmony_ci 14bbbf1280Sopenharmony_civoid seed_random(uint32 seed) { 15bbbf1280Sopenharmony_ci int i; 16bbbf1280Sopenharmony_ci 17bbbf1280Sopenharmony_ci seedptr = 0; 18bbbf1280Sopenharmony_ci for (i = 0; i < 55; i++) { 19bbbf1280Sopenharmony_ci seed = seed % 44488 * 48271 - seed / 44488 * 3399; 20bbbf1280Sopenharmony_ci seedbuf[i] = seed - 1; 21bbbf1280Sopenharmony_ci } 22bbbf1280Sopenharmony_ci} 23bbbf1280Sopenharmony_ci 24bbbf1280Sopenharmony_ciuint32 base_random(void) { 25bbbf1280Sopenharmony_ci seedptr %= 55; 26bbbf1280Sopenharmony_ci seedbuf[seedptr] += seedbuf[(seedptr+31)%55]; 27bbbf1280Sopenharmony_ci return seedbuf[seedptr++]; 28bbbf1280Sopenharmony_ci} 29bbbf1280Sopenharmony_ci 30bbbf1280Sopenharmony_ciuint32 random32(void) { 31bbbf1280Sopenharmony_ci uint32 a, b, b1, b2; 32bbbf1280Sopenharmony_ci a = base_random(); 33bbbf1280Sopenharmony_ci b = base_random(); 34bbbf1280Sopenharmony_ci for (b1 = 0x80000000, b2 = 1; b1 > b2; b1 >>= 1, b2 <<= 1) { 35bbbf1280Sopenharmony_ci uint32 b3 = b1 | b2; 36bbbf1280Sopenharmony_ci if ((b & b3) != 0 && (b & b3) != b3) 37bbbf1280Sopenharmony_ci b ^= b3; 38bbbf1280Sopenharmony_ci } 39bbbf1280Sopenharmony_ci return a ^ b; 40bbbf1280Sopenharmony_ci} 41bbbf1280Sopenharmony_ci 42bbbf1280Sopenharmony_ci/* 43bbbf1280Sopenharmony_ci * random_upto: generate a uniformly randomised number in the range 44bbbf1280Sopenharmony_ci * 0,...,limit-1. (Precondition: limit > 0.) 45bbbf1280Sopenharmony_ci * 46bbbf1280Sopenharmony_ci * random_upto_biased: generate a number in the same range, but with 47bbbf1280Sopenharmony_ci * the probability skewed towards the high end by means of taking the 48bbbf1280Sopenharmony_ci * maximum of 8*bias+1 samples from the uniform distribution on the 49bbbf1280Sopenharmony_ci * same range. (I don't know why bias is given in that curious way - 50bbbf1280Sopenharmony_ci * historical reasons, I expect.) 51bbbf1280Sopenharmony_ci * 52bbbf1280Sopenharmony_ci * For speed, I separate the implementation of random_upto into the 53bbbf1280Sopenharmony_ci * two stages of (a) generate a bitmask which reduces a 32-bit random 54bbbf1280Sopenharmony_ci * number to within a factor of two of the right range, (b) repeatedly 55bbbf1280Sopenharmony_ci * generate numbers in that range until one is small enough. Splitting 56bbbf1280Sopenharmony_ci * it up like that means that random_upto_biased can do (a) only once 57bbbf1280Sopenharmony_ci * even when it does (b) lots of times. 58bbbf1280Sopenharmony_ci */ 59bbbf1280Sopenharmony_ci 60bbbf1280Sopenharmony_cistatic uint32 random_upto_makemask(uint32 limit) { 61bbbf1280Sopenharmony_ci uint32 mask = 0xFFFFFFFF; 62bbbf1280Sopenharmony_ci int i; 63bbbf1280Sopenharmony_ci for (i = 16; i > 0; i >>= 1) 64bbbf1280Sopenharmony_ci if ((limit & (mask >> i)) == limit) 65bbbf1280Sopenharmony_ci mask >>= i; 66bbbf1280Sopenharmony_ci return mask; 67bbbf1280Sopenharmony_ci} 68bbbf1280Sopenharmony_ci 69bbbf1280Sopenharmony_cistatic uint32 random_upto_internal(uint32 limit, uint32 mask) { 70bbbf1280Sopenharmony_ci uint32 ret; 71bbbf1280Sopenharmony_ci do { 72bbbf1280Sopenharmony_ci ret = random32() & mask; 73bbbf1280Sopenharmony_ci } while (ret > limit); 74bbbf1280Sopenharmony_ci return ret; 75bbbf1280Sopenharmony_ci} 76bbbf1280Sopenharmony_ci 77bbbf1280Sopenharmony_ciuint32 random_upto(uint32 limit) { 78bbbf1280Sopenharmony_ci uint32 mask = random_upto_makemask(limit); 79bbbf1280Sopenharmony_ci return random_upto_internal(limit, mask); 80bbbf1280Sopenharmony_ci} 81bbbf1280Sopenharmony_ci 82bbbf1280Sopenharmony_ciuint32 random_upto_biased(uint32 limit, int bias) { 83bbbf1280Sopenharmony_ci uint32 mask = random_upto_makemask(limit); 84bbbf1280Sopenharmony_ci 85bbbf1280Sopenharmony_ci uint32 ret = random_upto_internal(limit, mask); 86bbbf1280Sopenharmony_ci while (bias--) { 87bbbf1280Sopenharmony_ci uint32 tmp; 88bbbf1280Sopenharmony_ci tmp = random_upto_internal(limit, mask); if (tmp < ret) ret = tmp; 89bbbf1280Sopenharmony_ci tmp = random_upto_internal(limit, mask); if (tmp < ret) ret = tmp; 90bbbf1280Sopenharmony_ci tmp = random_upto_internal(limit, mask); if (tmp < ret) ret = tmp; 91bbbf1280Sopenharmony_ci tmp = random_upto_internal(limit, mask); if (tmp < ret) ret = tmp; 92bbbf1280Sopenharmony_ci tmp = random_upto_internal(limit, mask); if (tmp < ret) ret = tmp; 93bbbf1280Sopenharmony_ci tmp = random_upto_internal(limit, mask); if (tmp < ret) ret = tmp; 94bbbf1280Sopenharmony_ci tmp = random_upto_internal(limit, mask); if (tmp < ret) ret = tmp; 95bbbf1280Sopenharmony_ci tmp = random_upto_internal(limit, mask); if (tmp < ret) ret = tmp; 96bbbf1280Sopenharmony_ci } 97bbbf1280Sopenharmony_ci 98bbbf1280Sopenharmony_ci return ret; 99bbbf1280Sopenharmony_ci} 100