From 50cc536324de269396b45289fd3f9193793a9855 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sun, 31 May 2020 17:03:14 +0200 Subject: [PATCH] libc: add random number generation with TinyMT TinyMT is licensed under its own terms. See src/std/tinymt/LICENSE.txt. --- README.md | 12 +++- include/gint/std/stdlib.h | 6 ++ src/core/start.c | 6 +- src/std/tinymt32/LICENSE.txt | 29 +++++++++ src/std/tinymt32/rand.c | 14 ++++ src/std/tinymt32/tinymt32.c | 121 +++++++++++++++++++++++++++++++++++ src/std/tinymt32/tinymt32.h | 40 ++++++++++++ 7 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 src/std/tinymt32/LICENSE.txt create mode 100644 src/std/tinymt32/rand.c create mode 100644 src/std/tinymt32/tinymt32.c create mode 100644 src/std/tinymt32/tinymt32.h diff --git a/README.md b/README.md index 9bb5dcd..20f6bb1 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,13 @@ This is free software: you may use it for any purpose, share it, and modify it as long as you share your changes. Credit is not required, but please let me know! +gint also includes third-party code that is distributed under its own license. +Currently, this only includes: + +* A stripped-down version of the [TinyMT random number generator](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index.html) + ([GitHub repository](https://github.com/MersenneTwister-Lab/TinyMT)) by + Mutsuo Saito and Makoto Matsumoto. See `src/std/tinymt32/LICENSE.txt`. + ## Programming interface Because of its free-standing design, gint's API provides direct and efficient @@ -52,7 +59,7 @@ or both. There are a few dependencies: default. fx-CG 50 developers probably want a g3a wrapper as well; the reference -implementation is tari's [mkg3a](https://gitlab.com/taricorp/mkg3a). This is +implementation is Tari's [mkg3a](https://gitlab.com/taricorp/mkg3a). This is needed at the very last compilation step to create the g3a file. On Arch Linux, you can use the [AUR/mkg3a](https://aur.archlinux.org/packages/mkg3a) package maintained directly by Tari. @@ -64,7 +71,8 @@ By default gint will be installed in the appropriate compiler folder, which is `$PREFIX/` for libraries and linker scripts, and `$PREFIX/include/gint/` for headers, where `PREFIX` is obtained by running `${toolchain}-gcc --print-search-dirs` and reading the line that starts with -`install:`. You can change this with the `--prefix` configure option. +`install:`. You can change this with the `--prefix` configure option, but +normally you don't need to. ### Building for fx-9860G II diff --git a/include/gint/std/stdlib.h b/include/gint/std/stdlib.h index 6024d28..ec4ad6f 100644 --- a/include/gint/std/stdlib.h +++ b/include/gint/std/stdlib.h @@ -19,4 +19,10 @@ void *calloc(size_t nmemb, size_t size); /* realloc(): Reallocate dynamic memory */ void *realloc(void *ptr, size_t size); +/* srand(): Seed the PRNG */ +void srand(unsigned int seed); + +/* rand(): Generate a pseudo-random number */ +int rand(void); + #endif /* GINT_STD_STDLIB */ diff --git a/src/core/start.c b/src/core/start.c index 2936d45..07c3be7 100644 --- a/src/core/start.c +++ b/src/core/start.c @@ -67,9 +67,9 @@ static void regclr(uint32_t *r, int32_t s) #define regclr(r, s) regclr(&r, (int32_t)&s) /* explore() - read data from a memory region to get it mapped by the system - This function accesses all the 1k-blocks between b and b + s. This - corresponds to region [b; b+s) when b and s are 1k-aligned. - @b Base pointer: first address checked + This function accesses all the 1k-blocks between b and b+s. This corresponds + to the region [b; b+s) when b and s are 1k-aligned. + @b Base pointer (first address checked) @s Size of region */ GSECTION(".pretext") static void explore(volatile void *b, int32_t s) diff --git a/src/std/tinymt32/LICENSE.txt b/src/std/tinymt32/LICENSE.txt new file mode 100644 index 0000000..af03886 --- /dev/null +++ b/src/std/tinymt32/LICENSE.txt @@ -0,0 +1,29 @@ +Copyright (c) 2011 Mutsuo Saito, Makoto Matsumoto, Hiroshima +University and The University of Tokyo. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the Hiroshima University nor the names of + its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/std/tinymt32/rand.c b/src/std/tinymt32/rand.c new file mode 100644 index 0000000..9800272 --- /dev/null +++ b/src/std/tinymt32/rand.c @@ -0,0 +1,14 @@ +#include +#include "tinymt32.h" + +static tinymt32_t random; + +void srand(unsigned int seed) +{ + tinymt32_init(&random, seed); +} + +int rand(void) +{ + return tinymt32_generate_uint32(&random); +} diff --git a/src/std/tinymt32/tinymt32.c b/src/std/tinymt32/tinymt32.c new file mode 100644 index 0000000..898ae98 --- /dev/null +++ b/src/std/tinymt32/tinymt32.c @@ -0,0 +1,121 @@ +/** + * @file tinymt32.c + * + * @brief Tiny Mersenne Twister only 127 bit internal state + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (The University of Tokyo) + * + * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto, + * Hiroshima University and The University of Tokyo. + * All rights reserved. + * + * The 3-clause BSD License is applied to this software, see + * LICENSE.txt + */ + +/* Note: this is a stripped-down version of TinyMT that only includes the + 32-bit integer generator. For the full version, please see + . */ + +#include "tinymt32.h" + +#define TINYMT32_SH0 1 +#define TINYMT32_SH1 10 +#define TINYMT32_SH8 8 +#define TINYMT32_MASK 0x7fffffff + +/** + * This function changes internal state of tinymt32. + * Users should not call this function directly. + * @param random tinymt internal status + */ +static void tinymt32_next_state(tinymt32_t * random) { + uint32_t x; + uint32_t y; + + y = random->status[3]; + x = (random->status[0] & TINYMT32_MASK) + ^ random->status[1] + ^ random->status[2]; + x ^= (x << TINYMT32_SH0); + y ^= (y >> TINYMT32_SH0) ^ x; + random->status[0] = random->status[1]; + random->status[1] = random->status[2]; + random->status[2] = x ^ (y << TINYMT32_SH1); + random->status[3] = y; + random->status[1] ^= -((int32_t)(y & 1)) & random->mat1; + random->status[2] ^= -((int32_t)(y & 1)) & random->mat2; +} + +/** + * This function outputs 32-bit unsigned integer from internal state. + * Users should not call this function directly. + * @param random tinymt internal status + * @return 32-bit unsigned pseudorandom number + */ +static uint32_t tinymt32_temper(tinymt32_t * random) { + uint32_t t0, t1; + t0 = random->status[3]; +#if defined(LINEARITY_CHECK) + t1 = random->status[0] + ^ (random->status[2] >> TINYMT32_SH8); +#else + t1 = random->status[0] + + (random->status[2] >> TINYMT32_SH8); +#endif + t0 ^= t1; + t0 ^= -((int32_t)(t1 & 1)) & random->tmat; + return t0; +} + +/** + * This function outputs 32-bit unsigned integer from internal state. + * @param random tinymt internal status + * @return 32-bit unsigned integer r (0 <= r < 2^32) + */ +uint32_t tinymt32_generate_uint32(tinymt32_t * random) { + tinymt32_next_state(random); + return tinymt32_temper(random); +} + +#define MIN_LOOP 8 +#define PRE_LOOP 8 + +/** + * This function certificate the period of 2^127-1. + * @param random tinymt state vector. + */ +static void period_certification(tinymt32_t * random) { + if ((random->status[0] & TINYMT32_MASK) == 0 && + random->status[1] == 0 && + random->status[2] == 0 && + random->status[3] == 0) { + random->status[0] = 'T'; + random->status[1] = 'I'; + random->status[2] = 'N'; + random->status[3] = 'Y'; + } +} + +/** + * This function initializes the internal state array with a 32-bit + * unsigned integer seed. + * @param random tinymt state vector. + * @param seed a 32-bit unsigned integer used as a seed. + */ +void tinymt32_init(tinymt32_t * random, uint32_t seed) { + random->status[0] = seed; + random->status[1] = random->mat1; + random->status[2] = random->mat2; + random->status[3] = random->tmat; + for (int i = 1; i < MIN_LOOP; i++) { + random->status[i & 3] ^= i + UINT32_C(1812433253) + * (random->status[(i - 1) & 3] + ^ (random->status[(i - 1) & 3] >> 30)); + } + period_certification(random); + for (int i = 0; i < PRE_LOOP; i++) { + tinymt32_next_state(random); + } +} diff --git a/src/std/tinymt32/tinymt32.h b/src/std/tinymt32/tinymt32.h new file mode 100644 index 0000000..9bb2f5c --- /dev/null +++ b/src/std/tinymt32/tinymt32.h @@ -0,0 +1,40 @@ +#ifndef TINYMT32_H +#define TINYMT32_H +/** + * @file tinymt32.h + * + * @brief Tiny Mersenne Twister only 127 bit internal state + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (University of Tokyo) + * + * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto, + * Hiroshima University and The University of Tokyo. + * All rights reserved. + * + * The 3-clause BSD License is applied to this software, see + * LICENSE.txt + */ + +/* Note: this is a stripped-down version of TinyMT that only includes the + 32-bit integer generator. For the full version, please see + . */ + +#include + +/** + * tinymt32 internal state vector and parameters + */ +struct TINYMT32_T { + uint32_t status[4]; + uint32_t mat1; + uint32_t mat2; + uint32_t tmat; +}; + +typedef struct TINYMT32_T tinymt32_t; + +uint32_t tinymt32_generate_uint32(tinymt32_t *random); +void tinymt32_init(tinymt32_t *random, uint32_t seed); + +#endif