/** * \file shr3.c * \brief SHR3 - Pseudo random number generator * * \subsection Copyright * Copyright (c) 2013 Michael Buesch * * \subsection License * Licensed under the terms of the GNU General Public License version 2. */ #include "shr3.h" #include "bitops.h" #include "util.h" /** SHR3 Zustand */ struct shr3_state { /** Das Schieberegister */ uint32_t reg; }; /** SHR3 Zustand - Instanz */ static struct shr3_state shr3; /** \brief Extrahiert Pseudozufallsbits aus dem Schieberegister. * * SHR3 Algorithmus entnommen aus einem sci.math Post * von George Marsaglia (Feb 25 2003, 10:25 am) * als Teil des KISS Generators: * http://groups.google.com/group/sci.math/msg/9959175f66dd138f * http://groups.google.com/group/sci.math/msg/7e499231fb1e58d3 * * \param nr_of_bits Die Anzahl der Bits die zu extrahieren sind. * Maximum 8. * * \return Gibt die Pseudozufallsbits in den LSBs zurueck. */ uint8_t shr3_get_random_bits(uint8_t nr_of_bits) { uint32_t y = shr3.reg; uint8_t ret = 0; while (nr_of_bits--) { /* Schieberegister weitertakten. */ y ^= y << 13; y ^= y >> 17; y ^= y << 5; /* Ein Bit aus dem Schieberegister entnehmen. */ ret = (ret << 1) | (y & 1); } shr3.reg = y; return ret; } /** \brief Extrahiert ein Pseudozufallsbyte aus dem Schieberegister. * Die Funktion achtet dabei auf eine gleichmaessige * Verteilung der moeglichen Zahlen. * * \param max_value Der groesste Wert, der zurueckgegeben werden kann. * * \return Gibt den Pseudozufallswert zurueck. */ uint8_t shr3_get_random_value_byte(uint8_t max_value) { uint8_t nr_of_bits, value; if (!max_value) return 0; /* Bitnummer (plus 1) des hoechstwertigsten gesetzten Bits * in max_value suchen. * Dies sucht effektiv die Zweierpotenz die * groesser oder gleich max_value ist. */ nr_of_bits = fls8(max_value); do { /* Zufallswert mit "nr_of_bits" zufaelligen Bits generieren. * Das generiert eine Zufallszahl zwischen 0 und * der naechsten Zweierpotenz die groesser oder * gleich max_value ist. */ value = shr3_get_random_bits(nr_of_bits); /* Erneut versuchen, wenn Wert groesser als max_value ist. */ } while (value > max_value); return value; } /** \brief Initialisiert das SHR3. * * \param seed Der Initialisierungswert des Schieberegisters. * Sollte nicht 0 sein. */ void shr3_init(uint32_t seed) { shr3.reg = seed ? seed : 0x7FFFFFFF; }