Last active
January 4, 2024 08:30
-
-
Save h20y6m/9ce02e903e3aa720fa310f951400c02f to your computer and use it in GitHub Desktop.
LaTeX: メルセンヌ・ツイスタ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% https://h20y6m.github.io/posts/2023-12-11-texadvent2023-2/ | |
\documentclass[a4paper,twocolumn]{article} | |
% https://github.com/h20y6m/latex-biguint | |
\usepackage{biguint} | |
\ExplSyntaxOn | |
% https://en.wikipedia.org/wiki/Mersenne_Twister | |
% constant n, m | |
\int_const:Nn \c_mt_n_int { 624 } | |
\int_const:Nn \c_mt_m_int { 397 } | |
% constant a | |
\biguint_const:Nn \c_mt_a_biguint { "9908 B0DF } | |
% constant u, d | |
\biguint_const:Nn \c_mt_u_biguint { 11 } | |
\biguint_const:Nn \c_mt_d_biguint { "FFFF FFFF } | |
% constant s, b | |
\biguint_const:Nn \c_mt_s_biguint { 7 } | |
\biguint_const:Nn \c_mt_b_biguint { "9D2C 5680 } | |
% constant t, c | |
\biguint_const:Nn \c_mt_t_biguint { 15 } | |
\biguint_const:Nn \c_mt_c_biguint { "EFC6 0000 } | |
% constant l | |
\biguint_const:Nn \c_mt_l_biguint { 18 } | |
% constant f | |
\biguint_const:Nn \c_mt_f_biguint { 1812433253 } | |
% state MT[0..(n-1)] | |
\int_step_inline:nnn { 0 } { \c_mt_n_int - 1 } | |
{ \biguint_new:c { g_mt_MT[ #1 ]_biguint } } | |
% index | |
\int_new:N \g_mt_index_int | |
\int_gset:Nn \g_mt_index_int { \c_mt_n_int + 1} | |
\biguint_new:N \g_mt_result_biguint | |
\biguint_const:Nn \c_mt_lower_mask_biguint { "7FFF FFFF } | |
\biguint_const:Nn \c_mt_upper_mask_biguint { "8000 0000 } | |
\biguint_const:Nn \c_mt_wbits_mask_biguint { "FFFF FFFF } | |
\biguint_const:Ne \c_mt_w_minus_two_biguint { \int_eval:n { 32 - 2 } } | |
\biguint_new:N \l__mt_tempa_biguint | |
\biguint_new:N \l__mt_tempb_biguint | |
\biguint_new:N \l__mt_y_biguint | |
\biguint_new:N \l__mt_x_biguint | |
\biguint_new:N \l__mt_xA_biguint | |
\cs_generate_variant:Nn \biguint_shr:NNN { NcN } | |
\cs_generate_variant:Nn \biguint_bitand:NNN { NcN } | |
\cs_generate_variant:Nn \biguint_gbitand:NNN { cNN } | |
\cs_generate_variant:Nn \biguint_bitxor:NNN { NcN } | |
\cs_generate_variant:Nn \biguint_gbitxor:NNN { ccN } | |
\msg_new:nnn { mt } { never-seeded } | |
{ Generator~was~never~seeded. } | |
\cs_new_protected:Npn \mt_seed_mt:n #1 | |
{ | |
\int_gset_eq:NN \g_mt_index_int \c_mt_n_int | |
\biguint_gset:cn { g_mt_MT[ 0 ]_biguint } { #1 } | |
\int_step_inline:nnn { 1 } { \c_mt_n_int - 1 } | |
{ | |
% MT[i-1] >> (w - 2) | |
\biguint_shr:NcN | |
\l__mt_tempa_biguint | |
{ g_mt_MT[ \int_eval:n { ##1 - 1 } ]_biguint } | |
\c_mt_w_minus_two_biguint | |
% MT[i-1] xor (...) | |
\biguint_bitxor:NcN | |
\l__mt_tempa_biguint | |
{ g_mt_MT[ \int_eval:n { ##1 - 1 } ]_biguint } | |
\l__mt_tempa_biguint | |
% f * (...) | |
\biguint_mul:NNN | |
\l__mt_tempa_biguint | |
\c_mt_f_biguint | |
\l__mt_tempa_biguint | |
% ... + i | |
\biguint_set:Nn \l__mt_tempb_biguint { ##1 } | |
\biguint_add:NNN | |
\l__mt_tempa_biguint | |
\l__mt_tempa_biguint | |
\l__mt_tempb_biguint | |
% MT[i] := lowest w bits of ... | |
\biguint_gbitand:cNN | |
{ g_mt_MT[ ##1 ]_biguint } | |
\l__mt_tempa_biguint | |
\c_mt_wbits_mask_biguint | |
} | |
} | |
\cs_new_protected:Npn \mt_extract_number: | |
{ | |
% if index >= n | |
\int_compare:nNnF { \g_mt_index_int } < { \c_mt_n_int } | |
{ | |
\int_compare:nNnT { \g_mt_index_int } > { \c_mt_n_int } | |
{ | |
\msg_error:nn { mt } { never-seeded } | |
} | |
\mt_twist: | |
} | |
% y := MT[index] | |
\biguint_set_eq:Nc | |
\l__mt_y_biguint | |
{ g_mt_MT[ \int_use:N \g_mt_index_int ]_biguint } | |
% y := y xor ((y >> u) and d) | |
\biguint_shr:NNN | |
\l__mt_tempa_biguint \l__mt_y_biguint \c_mt_u_biguint | |
\biguint_bitand:NNN | |
\l__mt_tempa_biguint \l__mt_tempa_biguint \c_mt_d_biguint | |
\biguint_bitxor:NN | |
\l__mt_y_biguint \l__mt_tempa_biguint | |
% y := y xor ((y << s) and b) | |
\biguint_shl:NNN | |
\l__mt_tempa_biguint \l__mt_y_biguint \c_mt_s_biguint | |
\biguint_bitand:NNN | |
\l__mt_tempa_biguint \l__mt_tempa_biguint \c_mt_b_biguint | |
\biguint_bitxor:NN | |
\l__mt_y_biguint \l__mt_tempa_biguint | |
% y := y xor ((y << t) and c) | |
\biguint_shl:NNN | |
\l__mt_tempa_biguint \l__mt_y_biguint \c_mt_t_biguint | |
\biguint_bitand:NNN | |
\l__mt_tempa_biguint \l__mt_tempa_biguint \c_mt_c_biguint | |
\biguint_bitxor:NN | |
\l__mt_y_biguint \l__mt_tempa_biguint | |
% y := y xor (y >> l) | |
\biguint_shr:NNN | |
\l__mt_tempa_biguint \l__mt_y_biguint \c_mt_l_biguint | |
\biguint_bitxor:NN | |
\l__mt_y_biguint \l__mt_tempa_biguint | |
% index := index + 1 | |
\int_gincr:N \g_mt_index_int | |
\biguint_gset_eq:NN | |
\g_mt_result_biguint \l__mt_y_biguint | |
} | |
\cs_new_protected:Npn \mt_twist: | |
{ | |
\int_step_inline:nnn { 0 } { \c_mt_n_int - 1 } | |
{ | |
% MT[i] and upper_mask | |
\biguint_bitand:NcN | |
\l__mt_x_biguint | |
{ g_mt_MT[ ##1 ]_biguint } | |
\c_mt_upper_mask_biguint | |
% MT[(i+1) mod n] and lower_mask | |
\biguint_bitand:NcN | |
\l__mt_tempa_biguint | |
{ g_mt_MT[ \int_eval:n { \int_mod:nn { ##1 + 1 } { \c_mt_n_int } } ]_biguint } | |
\c_mt_lower_mask_biguint | |
% x := ... | ... | |
\biguint_bitor:NN \l__mt_x_biguint \l__mt_tempa_biguint | |
% xA := x >> 1 | |
\biguint_shr:NNN \l__mt_xA_biguint \l__mt_x_biguint \c_one_biguint | |
% if (x mod 2) != 0 | |
\biguint_if_odd:NT \l__mt_x_biguint | |
{ | |
% xA := xA xor a | |
\biguint_bitxor:NN \l__mt_xA_biguint \c_mt_a_biguint | |
} | |
% MT[i] := MT[(i + m) mod n] xor xA | |
\biguint_gbitxor:ccN | |
{ g_mt_MT[ ##1 ]_biguint } | |
{ g_mt_MT[ \int_eval:n { \int_mod:nn { ##1 + \c_mt_m_int } { \c_mt_n_int } } ]_biguint } | |
\l__mt_xA_biguint | |
} | |
% index := 0 | |
\int_gzero:N \g_mt_index_int | |
} | |
\cs_new_protected:Npn \mt_show: | |
{ \mt__dump:N \tl_show:N } | |
\cs_new_protected:Npn \mt_log: | |
{ \mt__dump:N \tl_log:N } | |
\tl_new:N \l__mt_dump_tl | |
\cs_new_protected:Npn \mt__dump:N #1 | |
{ | |
\tl_clear:N \l__mt_dump_tl | |
\int_step_inline:nnn { 0 } { \c_mt_n_int - 1 } | |
{ | |
\tl_put_right:Ne \l__mt_dump_tl | |
{ \biguint_to_decimal:c { g_mt_MT[ ##1 ]_biguint } ~ } | |
} | |
\tl_put_right:Ne \l__mt_dump_tl | |
{ \int_use:N \g_mt_index_int } | |
#1 \l__mt_dump_tl | |
} | |
% LaTeX2e interface | |
\NewDocumentCommand \MTseed { m } | |
{ \mt_seed_mt:n {#1} } | |
\NewDocumentCommand \MTrand {} | |
{ \mt_extract_number: } | |
\NewExpandableDocumentCommand \MTnumber {} | |
{ \biguint_to_decimal:N \g_mt_result_biguint } | |
\ExplSyntaxOff | |
\usepackage{pgffor} | |
\begin{document} | |
\MTseed{5489} | |
\foreach \x in {1,...,10000} | |
{% | |
\MTrand | |
$ [\x] = \MTnumber $% | |
\par | |
}% | |
\end{document} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment