gcc реализация rand()
Я часами пытался найти реализацию функции rand(), используемой в gcc... Было бы очень признательно, если бы кто-то мог сослаться на меня с файлом, содержащим его реализацию или веб-сайт с реализацией.
Кстати, какой каталог (я использую Ubuntu, если это имеет значение) содержит стандартные реализации библиотеки c для компилятора gcc?
3 ответа
rand
состоит из вызова функции __random
который в основном просто вызывает другую функцию с именем __random_r
в random_r.c.
Обратите внимание, что приведенные выше имена функций являются гиперссылками на исходный репозиторий glibc версии 2.28.
Библиотека случайных чисел glibc поддерживает два вида генератора: простой линейный конгруэнтный и более сложный регистр сдвига с линейной обратной связью. Можно создать экземпляры любого из них, но глобальный генератор по умолчанию, используемый при вызове rand
, использует генератор регистров сдвига с линейной обратной связью (см. определение unsafe_state.rand_type
).
Вы найдете реализацию библиотеки C, используемую GCC в проекте GNU GLIBC.
Вы можете скачать его источники и вы должны найти rand()
реализация. Источники с определениями функций обычно не устанавливаются в дистрибутив Linux. Только заголовочные файлы, которые, я думаю, вы уже знаете, обычно хранятся в /usr/include
каталог.
Если вы знакомы с управлением исходным кодом GIT, вы можете сделать:
$ git clone git://sourceware.org/git/glibc.git
Получить исходный код GLIBC.
Файлы доступны по FTP. Я обнаружил, что есть еще
rand()
используется в , который из
[glibc][2]
. Из полученной версии
2.32 (glibc-2.32.tar.gz)отсюдаstdlib
папка содержит
random.c
файл, который объясняет, что используется простой линейный конгруэнтный алгоритм. В папке также есть
rand.c
а также
rand_r.c
который может показать вам больше исходного кода.
stdlib.h
содержащиеся в той же папке, покажут вам значения, используемые для макросов, таких как
RAND_MAX
.
/* Улучшенный пакет генерации случайных чисел. В дополнение к стандартному интерфейсу, подобному rand()/srand(), этот пакет также имеет специальный интерфейс информации о состоянии. Подпрограмма initstate() вызывается с начальным значением, массивом байтов и количеством переданных байтов; затем этот массив инициализируется, чтобы содержать информацию для генерации случайных чисел с таким количеством информации о состоянии. Хорошие размеры для объема информации о состоянии: 32, 64, 128 и 256 байт. Состояние можно изменить, вызвав функцию setstate() с тем же массивом, который был инициализирован с помощью initstate(). По умолчанию пакет работает со 128 байтами
информации о состоянии и генерирует гораздо более качественные случайные числа, чем линейный пакет.
конгруэнтный генератор. Если объем информации о состоянии меньше 32 байт, используется простой линейный конгруэнтный ГСЧ. Внутри информация о состоянии обрабатывается как массив длинных значений; нулевой элемент массива — это тип используемого ГСЧ (маленькое целое число); остальная часть массива представляет собой информацию о состоянии для ГСЧ. Таким образом, 32 байта информации о состоянии дадут информацию о состоянии размером 7 длин, что позволит получить полином седьмой степени. (Примечание: нулевое слово состояния
информация также содержит некоторую другую информацию, хранящуюся в ней; подробности см. в setstate). Метод генерации случайных чисел представляет собой подход с линейным регистром сдвига с обратной связью, в котором используются трехчлены (поскольку таким образом можно суммировать меньше членов). При таком подходе младший значащий бит всех чисел в таблице состояний будет действовать как регистр сдвига с линейной обратной связью и будет иметь период 2^deg - 1(где deg — степень используемого полинома, при условии, что полином неприводим и примитивен). Биты более высокого порядка будут иметь более длинные периоды, поскольку на их значения также влияют псевдослучайные переносы младших битов. Общий
период генератора приблизительно равен град*(2град - 1); Таким образом, удвоение объема информации о состоянии оказывает огромное влияние на
период генератора. Примечание. Градус *(2 градус - 1) является приблизительным значением, подходящим только для больших градусов, когда период сдвигового регистра является доминирующим фактором. Когда deg равен семи, период на самом деле намного длиннее, чем 7*(2**7 - 1), предсказанный этой формулой. */