libc: add random number generation with TinyMT

TinyMT is licensed under its own terms. See src/std/tinymt/LICENSE.txt.
This commit is contained in:
Lephe 2020-05-31 17:03:14 +02:00
parent 5ff1662e61
commit 50cc536324
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
7 changed files with 223 additions and 5 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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)

View File

@ -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.

14
src/std/tinymt32/rand.c Normal file
View File

@ -0,0 +1,14 @@
#include <gint/std/stdlib.h>
#include "tinymt32.h"
static tinymt32_t random;
void srand(unsigned int seed)
{
tinymt32_init(&random, seed);
}
int rand(void)
{
return tinymt32_generate_uint32(&random);
}

121
src/std/tinymt32/tinymt32.c Normal file
View File

@ -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
<https://github.com/MersenneTwister-Lab/TinyMT>. */
#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);
}
}

View File

@ -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
<https://github.com/MersenneTwister-Lab/TinyMT>. */
#include <stdint.h>
/**
* 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