Compare commits

...

4 Commits

Author SHA1 Message Date
Dane Sabo
ebb3714379 vault backup: 2026-01-21 10:59:15 2026-01-21 10:59:15 -05:00
Dane Sabo
45b4e6b0c1 vault backup: 2026-01-21 10:56:16 2026-01-21 10:56:16 -05:00
Dane Sabo
9c9cb4aecb vault backup: 2026-01-14 15:47:27 2026-01-14 15:47:27 -05:00
Dane Sabo
9dab0b4ef1 vault backup: 2026-01-14 13:42:21 2026-01-14 13:42:21 -05:00
4324 changed files with 30098 additions and 1574 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -14,12 +14,14 @@ else
set shortmess=aoO set shortmess=aoO
endif endif
badd +44 custom/configs/lspconfig.lua badd +44 custom/configs/lspconfig.lua
badd +197 ~/.config/nvim/lua/custom/plugins.lua badd +18 ~/.config/nvim/lua/custom/plugins.lua
badd +6 custom/journal.lua badd +6 custom/journal.lua
badd +20 custom/language_specific_commands/markdown_and_tex.lua
argglobal argglobal
%argdel %argdel
edit ~/.config/nvim/lua/custom/plugins.lua edit ~/.config/nvim/lua/custom/plugins.lua
argglobal argglobal
balt custom/configs/lspconfig.lua
setlocal foldmethod=manual setlocal foldmethod=manual
setlocal foldexpr=v:lua.vim.treesitter.foldexpr() setlocal foldexpr=v:lua.vim.treesitter.foldexpr()
setlocal foldmarker={{{,}}} setlocal foldmarker={{{,}}}
@ -30,12 +32,12 @@ setlocal foldnestmax=20
setlocal foldenable setlocal foldenable
silent! normal! zE silent! normal! zE
let &fdl = &fdl let &fdl = &fdl
let s:l = 197 - ((52 * winheight(0) + 34) / 68) let s:l = 18 - ((17 * winheight(0) + 33) / 67)
if s:l < 1 | let s:l = 1 | endif if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l keepjumps exe s:l
normal! zt normal! zt
keepjumps 197 keepjumps 18
normal! 0 normal! 017|
tabnext 1 tabnext 1
if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal' if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'
silent exe 'bwipe ' . s:wipebuf silent exe 'bwipe ' . s:wipebuf

Binary file not shown.

BIN
Class_Work/.DS_Store vendored Normal file

Binary file not shown.

BIN
Class_Work/me2243/.DS_Store vendored Normal file

Binary file not shown.

BIN
Class_Work/me2243/HW1/.DS_Store vendored Normal file

Binary file not shown.

1046
Class_Work/me2243/HW1/solutions/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
[package]
name = "solutions"
version = "0.1.0"
edition = "2024"
[dependencies]
statrs = "0.17"
plotters = "0.3"

View File

@ -0,0 +1,46 @@
# LaTeX Writeup Notes
## Claude Aside - RANDU Mathematical Verification
**Context:** During development, Claude added a mathematical verification to prove RANDU's planar structure beyond just visual inspection.
**The Insight:**
RANDU's fatal flaw isn't just visible in 3D plots - it can be mathematically proven. Every triplet of consecutive values (x_n, x_{n+1}, x_{n+2}) satisfies the linear relationship:
```
x_{n+2} ≡ 6·x_{n+1} - 9·x_n (mod 2^31)
```
**Why This Matters:**
1. This equation defines a plane in 3D space
2. All RANDU outputs lie on just 15 such parallel planes
3. This makes RANDU catastrophically bad for Monte Carlo simulations
4. The verification code (see problem1.rs:92-109) proves this relationship holds for every triplet
**For LaTeX Writeup:**
Consider adding this mathematical verification as a proof/aside that:
- Shows the limitation isn't just visual - it's algebraically constrained
- Demonstrates that statistical tests (mean, std dev) alone miss critical structural flaws
- Explains *why* RANDU fails: deterministic linear constraint reduces 3D space to 15 planes
**Cool Factor:**
This is a case where the AI assistant didn't just visualize the problem - it provided mathematical proof of the underlying structural flaw. The self-checking approach (generating triplets and verifying the constraint) demonstrates both the problem and a rigorous testing methodology.
---
## Other Sections to Include
### Problem 1A - Basic LCG Implementation
- Show first 5 random numbers
- Discuss LCG formula: x_{n+1} = (a·x_n + c) mod m
### Problem 1B - Comparison
- Good LCG vs RANDU
- Statistics comparison (both look fine!)
- 3D scatter plots (visual difference)
- Mathematical verification (definitive proof)
### Figures to Include
- `good_lcg_3d.png` - Uniform 3D distribution
- `randu_3d.png` - Visible planar structure
- Consider adding histogram comparison if needed

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

View File

@ -0,0 +1,65 @@
\relax
\providecommand\hyper@newdestlabel[2]{}
\providecommand\HyField@AuxAddToFields[1]{}
\providecommand\HyField@AuxAddToCoFields[2]{}
\@writefile{toc}{\contentsline {section}{\numberline {1}Preamble: Implementation in Rust}{2}{section.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {1.1}Why Rust?}{2}{subsection.1.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {1.2}Code Architecture}{2}{subsection.1.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {1.3}The \texttt {RandomGenerator} Trait}{2}{subsection.1.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {1.4}Key Rust Syntax for Non-Rustaceans}{3}{subsection.1.4}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {2}Problem 1: Linear Congruential Generator}{3}{section.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Part (a): LCG Implementation}{3}{subsection.2.1}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{\numberline {1}{\ignorespaces LCG Implementation (src/lcg.rs)}}{3}{lstlisting.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Part (b): Good LCG vs RANDU Comparison}{4}{subsection.2.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.2.1}Statistical Results}{4}{subsubsection.2.2.1}\protected@file@percent }
\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces Statistical comparison of Good LCG and RANDU over 16,384 samples}}{4}{table.caption.4}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.2.2}Histograms}{5}{subsubsection.2.2.2}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Histograms of Good LCG and RANDU. Both appear uniformly distributed.}}{5}{figure.caption.5}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.2.3}3D Scatter Plots}{5}{subsubsection.2.2.3}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces 3D scatter plots of consecutive triplets $(u_n, u_{n+1}, u_{n+2})$}}{5}{figure.caption.6}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.2.4}Analysis}{5}{subsubsection.2.2.4}\protected@file@percent }
\@writefile{toc}{\contentsline {paragraph}{Mathematical Verification (Claude Aside):}{5}{section*.7}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {3}Problem 2: Linear Feedback Shift Register (Xorshift32)}{6}{section.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Part (a): Xorshift32 Implementation}{6}{subsection.3.1}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{\numberline {2}{\ignorespaces LFSR/Xorshift Implementation (src/lfsr.rs)}}{6}{lstlisting.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Part (b): Statistical Analysis}{7}{subsection.3.2}\protected@file@percent }
\@writefile{lot}{\contentsline {table}{\numberline {2}{\ignorespaces Xorshift32 statistics over 100,000 samples}}{7}{table.caption.8}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Xorshift32 analysis showing uniform distribution and no visible correlation structure}}{7}{figure.caption.9}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.2.1}Comparison to LCG}{7}{subsubsection.3.2.1}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {4}Problem 3: Permuted Congruential Generator (PCG32)}{7}{section.4}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Part (a): AI-Generated Code with Annotations}{7}{subsection.4.1}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{\numberline {3}{\ignorespaces PCG32 Implementation with Annotations (src/pcg.rs)}}{7}{lstlisting.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}Understanding PCG32}{9}{subsection.4.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}Statistical Results}{9}{subsection.4.3}\protected@file@percent }
\@writefile{lot}{\contentsline {table}{\numberline {3}{\ignorespaces PCG32 statistics over 100,000 samples}}{9}{table.caption.10}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces PCG32 analysis showing excellent statistical properties (<- Claude is proud of itself)}}{10}{figure.caption.11}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {5}Problem 4: Rule 30 Cellular Automaton}{10}{section.5}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {5.1}Part (a): Rule 30 Implementation}{10}{subsection.5.1}\protected@file@percent }
\@writefile{lot}{\contentsline {table}{\numberline {4}{\ignorespaces Rule 30 transition table (binary: 00011110 = 30 in decimal)}}{10}{table.caption.12}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{\numberline {4}{\ignorespaces Rule 30 Implementation (src/rule30.rs)}}{10}{lstlisting.4}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2}Part (b): Statistical Analysis}{11}{subsection.5.2}\protected@file@percent }
\@writefile{lot}{\contentsline {table}{\numberline {5}{\ignorespaces Rule 30 statistics over 100,000 samples (32-cell implementation)}}{11}{table.caption.13}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces Rule 30 analysis showing good statistical properties}}{12}{figure.caption.14}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.1}Comparison to LCG and LFSR}{12}{subsubsection.5.2.1}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {6}Summary and Conclusions}{12}{section.6}\protected@file@percent }
\@writefile{lot}{\contentsline {table}{\numberline {6}{\ignorespaces Summary comparison of all implemented PRNGs}}{12}{table.caption.15}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {A}Complete Code Listings}{13}{appendix.A}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {A.1}lib.rs -- Main Library with Trait Definition}{13}{subsection.A.1}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{src/lib.rs}{13}{lstlisting.-2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2}lcg.rs -- Linear Congruential Generator}{13}{subsection.A.2}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{src/lcg.rs}{13}{lstlisting.-3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {A.3}lfsr.rs -- Linear Feedback Shift Register}{14}{subsection.A.3}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{src/lfsr.rs}{14}{lstlisting.-4}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4}pcg.rs -- Permuted Congruential Generator}{15}{subsection.A.4}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{src/pcg.rs}{15}{lstlisting.-5}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {A.5}rule30.rs -- Rule 30 Cellular Automaton}{17}{subsection.A.5}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{src/rule30.rs}{17}{lstlisting.-6}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {A.6}problem1.rs -- LCG Analysis Program}{18}{subsection.A.6}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{src/bin/problem1.rs}{18}{lstlisting.-7}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {A.7}problem2.rs -- LFSR Analysis Program}{22}{subsection.A.7}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{src/bin/problem2.rs}{22}{lstlisting.-8}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {A.8}problem3.rs -- PCG32 Analysis Program}{24}{subsection.A.8}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{src/bin/problem3.rs}{24}{lstlisting.-9}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {A.9}problem4.rs -- Rule 30 Analysis Program}{27}{subsection.A.9}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{src/bin/problem4.rs}{27}{lstlisting.-10}\protected@file@percent }
\gdef \@abspage@last{30}

View File

@ -0,0 +1,685 @@
This is pdfTeX, Version 3.141592653-2.6-1.40.27 (TeX Live 2025) (preloaded format=pdflatex 2025.3.8) 21 JAN 2026 08:51
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
**report.tex
(./report.tex
LaTeX2e <2024-11-01> patch level 2
L3 programming layer <2025-01-18>
(/usr/local/texlive/2025/texmf-dist/tex/latex/base/article.cls
Document Class: article 2024/06/29 v1.4n Standard LaTeX document class
(/usr/local/texlive/2025/texmf-dist/tex/latex/base/size11.clo
File: size11.clo 2024/06/29 v1.4n Standard LaTeX file (size option)
)
\c@part=\count196
\c@section=\count197
\c@subsection=\count198
\c@subsubsection=\count199
\c@paragraph=\count266
\c@subparagraph=\count267
\c@figure=\count268
\c@table=\count269
\abovecaptionskip=\skip49
\belowcaptionskip=\skip50
\bibindent=\dimen141
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/geometry/geometry.sty
Package: geometry 2020/01/02 v5.9 Page Geometry
(/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/keyval.sty
Package: keyval 2022/05/29 v1.15 key=value parser (DPC)
\KV@toks@=\toks17
)
(/usr/local/texlive/2025/texmf-dist/tex/generic/iftex/ifvtex.sty
Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead.
(/usr/local/texlive/2025/texmf-dist/tex/generic/iftex/iftex.sty
Package: iftex 2024/12/12 v1.0g TeX engine tests
))
\Gm@cnth=\count270
\Gm@cntv=\count271
\c@Gm@tempcnt=\count272
\Gm@bindingoffset=\dimen142
\Gm@wd@mp=\dimen143
\Gm@odd@mp=\dimen144
\Gm@even@mp=\dimen145
\Gm@layoutwidth=\dimen146
\Gm@layoutheight=\dimen147
\Gm@layouthoffset=\dimen148
\Gm@layoutvoffset=\dimen149
\Gm@dimlist=\toks18
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsmath.sty
Package: amsmath 2024/11/05 v2.17t AMS math features
\@mathmargin=\skip51
For additional information on amsmath, use the `?' option.
(/usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amstext.sty
Package: amstext 2021/08/26 v2.01 AMS text
(/usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsgen.sty
File: amsgen.sty 1999/11/30 v2.0 generic functions
\@emptytoks=\toks19
\ex@=\dimen150
))
(/usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsbsy.sty
Package: amsbsy 1999/11/29 v1.2d Bold Symbols
\pmbraise@=\dimen151
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/amsmath/amsopn.sty
Package: amsopn 2022/04/08 v2.04 operator names
)
\inf@bad=\count273
LaTeX Info: Redefining \frac on input line 233.
\uproot@=\count274
\leftroot@=\count275
LaTeX Info: Redefining \overline on input line 398.
LaTeX Info: Redefining \colon on input line 409.
\classnum@=\count276
\DOTSCASE@=\count277
LaTeX Info: Redefining \ldots on input line 495.
LaTeX Info: Redefining \dots on input line 498.
LaTeX Info: Redefining \cdots on input line 619.
\Mathstrutbox@=\box52
\strutbox@=\box53
LaTeX Info: Redefining \big on input line 721.
LaTeX Info: Redefining \Big on input line 722.
LaTeX Info: Redefining \bigg on input line 723.
LaTeX Info: Redefining \Bigg on input line 724.
\big@size=\dimen152
LaTeX Font Info: Redeclaring font encoding OML on input line 742.
LaTeX Font Info: Redeclaring font encoding OMS on input line 743.
\macc@depth=\count278
LaTeX Info: Redefining \bmod on input line 904.
LaTeX Info: Redefining \pmod on input line 909.
LaTeX Info: Redefining \smash on input line 939.
LaTeX Info: Redefining \relbar on input line 969.
LaTeX Info: Redefining \Relbar on input line 970.
\c@MaxMatrixCols=\count279
\dotsspace@=\muskip17
\c@parentequation=\count280
\dspbrk@lvl=\count281
\tag@help=\toks20
\row@=\count282
\column@=\count283
\maxfields@=\count284
\andhelp@=\toks21
\eqnshift@=\dimen153
\alignsep@=\dimen154
\tagshift@=\dimen155
\tagwidth@=\dimen156
\totwidth@=\dimen157
\lineht@=\dimen158
\@envbody=\toks22
\multlinegap=\skip52
\multlinetaggap=\skip53
\mathdisplay@stack=\toks23
LaTeX Info: Redefining \[ on input line 2953.
LaTeX Info: Redefining \] on input line 2954.
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/amssymb.sty
Package: amssymb 2013/01/14 v3.01 AMS font symbols
(/usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/amsfonts.sty
Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support
\symAMSa=\mathgroup4
\symAMSb=\mathgroup5
LaTeX Font Info: Redeclaring math symbol \hbar on input line 98.
LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold'
(Font) U/euf/m/n --> U/euf/b/n on input line 106.
))
(/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/graphicx.sty
Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR)
(/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/graphics.sty
Package: graphics 2024/08/06 v1.4g Standard LaTeX Graphics (DPC,SPQR)
(/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/trig.sty
Package: trig 2023/12/02 v1.11 sin cos tan (DPC)
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/graphics-cfg/graphics.cfg
File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration
)
Package graphics Info: Driver file: pdftex.def on input line 106.
(/usr/local/texlive/2025/texmf-dist/tex/latex/graphics-def/pdftex.def
File: pdftex.def 2024/04/13 v1.2c Graphics/color driver for pdftex
))
\Gin@req@height=\dimen159
\Gin@req@width=\dimen160
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/listings/listings.sty
\lst@mode=\count285
\lst@gtempboxa=\box54
\lst@token=\toks24
\lst@length=\count286
\lst@currlwidth=\dimen161
\lst@column=\count287
\lst@pos=\count288
\lst@lostspace=\dimen162
\lst@width=\dimen163
\lst@newlines=\count289
\lst@lineno=\count290
\lst@maxwidth=\dimen164
(/usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstpatch.sty
File: lstpatch.sty 2024/09/23 1.10c (Carsten Heinz)
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/listings/lstmisc.sty
File: lstmisc.sty 2024/09/23 1.10c (Carsten Heinz)
\c@lstnumber=\count291
\lst@skipnumbers=\count292
\lst@framebox=\box55
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/listings/listings.cfg
File: listings.cfg 2024/09/23 1.10c listings configuration
))
Package: listings 2024/09/23 1.10c (Carsten Heinz)
(/usr/local/texlive/2025/texmf-dist/tex/latex/xcolor/xcolor.sty
Package: xcolor 2024/09/29 v3.02 LaTeX color extensions (UK)
(/usr/local/texlive/2025/texmf-dist/tex/latex/graphics-cfg/color.cfg
File: color.cfg 2016/01/02 v1.6 sample color configuration
)
Package xcolor Info: Driver file: pdftex.def on input line 274.
(/usr/local/texlive/2025/texmf-dist/tex/latex/graphics/mathcolor.ltx)
Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1349.
Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1353.
Package xcolor Info: Model `RGB' extended on input line 1365.
Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1367.
Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1368.
Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1369.
Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1370.
Package xcolor Info: Model `Gray' substituted by `gray' on input line 1371.
Package xcolor Info: Model `wave' substituted by `hsb' on input line 1372.
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/hyperref.sty
Package: hyperref 2024-11-05 v7.01l Hypertext links for LaTeX
(/usr/local/texlive/2025/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty
Package: kvsetkeys 2022-10-05 v1.19 Key value parser (HO)
)
(/usr/local/texlive/2025/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty
Package: kvdefinekeys 2019-12-19 v1.6 Define keys (HO)
)
(/usr/local/texlive/2025/texmf-dist/tex/generic/pdfescape/pdfescape.sty
Package: pdfescape 2019/12/09 v1.15 Implements pdfTeX's escape features (HO)
(/usr/local/texlive/2025/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty
Package: ltxcmds 2023-12-04 v1.26 LaTeX kernel commands for general use (HO)
)
(/usr/local/texlive/2025/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty
Package: pdftexcmds 2020-06-27 v0.33 Utility functions of pdfTeX for LuaTeX (HO
)
(/usr/local/texlive/2025/texmf-dist/tex/generic/infwarerr/infwarerr.sty
Package: infwarerr 2019/12/03 v1.5 Providing info/warning/error messages (HO)
)
Package pdftexcmds Info: \pdf@primitive is available.
Package pdftexcmds Info: \pdf@ifprimitive is available.
Package pdftexcmds Info: \pdfdraftmode found.
))
(/usr/local/texlive/2025/texmf-dist/tex/latex/hycolor/hycolor.sty
Package: hycolor 2020-01-27 v1.10 Color options for hyperref/bookmark (HO)
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/nameref.sty
Package: nameref 2023-11-26 v2.56 Cross-referencing by name of section
(/usr/local/texlive/2025/texmf-dist/tex/latex/refcount/refcount.sty
Package: refcount 2019/12/15 v3.6 Data extraction from label references (HO)
)
(/usr/local/texlive/2025/texmf-dist/tex/generic/gettitlestring/gettitlestring.s
ty
Package: gettitlestring 2019/12/15 v1.6 Cleanup title references (HO)
(/usr/local/texlive/2025/texmf-dist/tex/latex/kvoptions/kvoptions.sty
Package: kvoptions 2022-06-15 v3.15 Key value format for package options (HO)
))
\c@section@level=\count293
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/etoolbox/etoolbox.sty
Package: etoolbox 2025/02/11 v2.5l e-TeX tools for LaTeX (JAW)
\etb@tempcnta=\count294
)
(/usr/local/texlive/2025/texmf-dist/tex/generic/stringenc/stringenc.sty
Package: stringenc 2019/11/29 v1.12 Convert strings between diff. encodings (HO
)
)
\@linkdim=\dimen165
\Hy@linkcounter=\count295
\Hy@pagecounter=\count296
(/usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/pd1enc.def
File: pd1enc.def 2024-11-05 v7.01l Hyperref: PDFDocEncoding definition (HO)
Now handling font encoding PD1 ...
... no UTF-8 mapping file for font encoding PD1
)
(/usr/local/texlive/2025/texmf-dist/tex/generic/intcalc/intcalc.sty
Package: intcalc 2019/12/15 v1.3 Expandable calculations with integers (HO)
)
\Hy@SavedSpaceFactor=\count297
(/usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/puenc.def
File: puenc.def 2024-11-05 v7.01l Hyperref: PDF Unicode definition (HO)
Now handling font encoding PU ...
... no UTF-8 mapping file for font encoding PU
)
Package hyperref Info: Hyper figures OFF on input line 4157.
Package hyperref Info: Link nesting OFF on input line 4162.
Package hyperref Info: Hyper index ON on input line 4165.
Package hyperref Info: Plain pages OFF on input line 4172.
Package hyperref Info: Backreferencing OFF on input line 4177.
Package hyperref Info: Implicit mode ON; LaTeX internals redefined.
Package hyperref Info: Bookmarks ON on input line 4424.
\c@Hy@tempcnt=\count298
(/usr/local/texlive/2025/texmf-dist/tex/latex/url/url.sty
\Urlmuskip=\muskip18
Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc.
)
LaTeX Info: Redefining \url on input line 4763.
\XeTeXLinkMargin=\dimen166
(/usr/local/texlive/2025/texmf-dist/tex/generic/bitset/bitset.sty
Package: bitset 2019/12/09 v1.3 Handle bit-vector datatype (HO)
(/usr/local/texlive/2025/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty
Package: bigintcalc 2019/12/15 v1.5 Expandable calculations on big integers (HO
)
))
\Fld@menulength=\count299
\Field@Width=\dimen167
\Fld@charsize=\dimen168
Package hyperref Info: Hyper figures OFF on input line 6042.
Package hyperref Info: Link nesting OFF on input line 6047.
Package hyperref Info: Hyper index ON on input line 6050.
Package hyperref Info: backreferencing OFF on input line 6057.
Package hyperref Info: Link coloring OFF on input line 6062.
Package hyperref Info: Link coloring with OCG OFF on input line 6067.
Package hyperref Info: PDF/A mode OFF on input line 6072.
(/usr/local/texlive/2025/texmf-dist/tex/latex/base/atbegshi-ltx.sty
Package: atbegshi-ltx 2021/01/10 v1.0c Emulation of the original atbegshi
package with kernel methods
)
\Hy@abspage=\count300
\c@Item=\count301
\c@Hfootnote=\count302
)
Package hyperref Info: Driver (autodetected): hpdftex.
(/usr/local/texlive/2025/texmf-dist/tex/latex/hyperref/hpdftex.def
File: hpdftex.def 2024-11-05 v7.01l Hyperref driver for pdfTeX
(/usr/local/texlive/2025/texmf-dist/tex/latex/base/atveryend-ltx.sty
Package: atveryend-ltx 2020/08/19 v1.0a Emulation of the original atveryend pac
kage
with kernel methods
)
\Fld@listcount=\count303
\c@bookmark@seq@number=\count304
(/usr/local/texlive/2025/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty
Package: rerunfilecheck 2022-07-10 v1.10 Rerun checks for auxiliary files (HO)
(/usr/local/texlive/2025/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty
Package: uniquecounter 2019/12/15 v1.4 Provide unlimited unique counter (HO)
)
Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2
85.
)
\Hy@SectionHShift=\skip54
) (/usr/local/texlive/2025/texmf-dist/tex/latex/float/float.sty
Package: float 2001/11/08 v1.3d Float enhancements (AL)
\c@float@type=\count305
\float@exts=\toks25
\float@box=\box56
\@float@everytoks=\toks26
\@floatcapt=\box57
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/booktabs/booktabs.sty
Package: booktabs 2020/01/12 v1.61803398 Publication quality tables
\heavyrulewidth=\dimen169
\lightrulewidth=\dimen170
\cmidrulewidth=\dimen171
\belowrulesep=\dimen172
\belowbottomsep=\dimen173
\aboverulesep=\dimen174
\abovetopsep=\dimen175
\cmidrulesep=\dimen176
\cmidrulekern=\dimen177
\defaultaddspace=\dimen178
\@cmidla=\count306
\@cmidlb=\count307
\@aboverulesep=\dimen179
\@belowrulesep=\dimen180
\@thisruleclass=\count308
\@lastruleclass=\count309
\@thisrulewidth=\dimen181
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/caption/caption.sty
Package: caption 2023/08/05 v3.6o Customizing captions (AR)
(/usr/local/texlive/2025/texmf-dist/tex/latex/caption/caption3.sty
Package: caption3 2023/07/31 v2.4d caption3 kernel (AR)
\caption@tempdima=\dimen182
\captionmargin=\dimen183
\caption@leftmargin=\dimen184
\caption@rightmargin=\dimen185
\caption@width=\dimen186
\caption@indent=\dimen187
\caption@parindent=\dimen188
\caption@hangindent=\dimen189
Package caption Info: Standard document class detected.
)
\c@caption@flags=\count310
\c@continuedfloat=\count311
Package caption Info: float package is loaded.
Package caption Info: hyperref package is loaded.
Package caption Info: listings package is loaded.
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/caption/subcaption.sty
Package: subcaption 2023/07/28 v1.6b Sub-captions (AR)
Package caption Info: New subtype `subfigure' on input line 238.
\c@subfigure=\count312
Package caption Info: New subtype `subtable' on input line 238.
\c@subtable=\count313
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/base/inputenc.sty
Package: inputenc 2024/02/08 v1.3d Input encoding file
\inpenc@prehook=\toks27
\inpenc@posthook=\toks28
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/base/fontenc.sty
Package: fontenc 2021/04/29 v2.0v Standard LaTeX package
)
(/usr/local/texlive/2025/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
File: l3backend-pdftex.def 2024-05-08 L3 backend support: PDF output (pdfTeX)
\l__color_backend_stack_int=\count314
\l__pdf_internal_box=\box58
)
(./report.aux)
\openout1 = `report.aux'.
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 52.
LaTeX Font Info: ... okay on input line 52.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 52.
LaTeX Font Info: ... okay on input line 52.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 52.
LaTeX Font Info: ... okay on input line 52.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 52.
LaTeX Font Info: ... okay on input line 52.
LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 52.
LaTeX Font Info: ... okay on input line 52.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 52.
LaTeX Font Info: ... okay on input line 52.
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 52.
LaTeX Font Info: ... okay on input line 52.
LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 52.
LaTeX Font Info: ... okay on input line 52.
LaTeX Font Info: Checking defaults for PU/pdf/m/n on input line 52.
LaTeX Font Info: ... okay on input line 52.
*geometry* driver: auto-detecting
*geometry* detected driver: pdftex
*geometry* verbose mode - [ preamble ] result:
* driver: pdftex
* paper: <default>
* layout: <same size as paper>
* layoutoffset:(h,v)=(0.0pt,0.0pt)
* modes:
* h-part:(L,W,R)=(72.26999pt, 469.75502pt, 72.26999pt)
* v-part:(T,H,B)=(72.26999pt, 650.43001pt, 72.26999pt)
* \paperwidth=614.295pt
* \paperheight=794.96999pt
* \textwidth=469.75502pt
* \textheight=650.43001pt
* \oddsidemargin=0.0pt
* \evensidemargin=0.0pt
* \topmargin=-37.0pt
* \headheight=12.0pt
* \headsep=25.0pt
* \topskip=11.0pt
* \footskip=30.0pt
* \marginparwidth=59.0pt
* \marginparsep=10.0pt
* \columnsep=10.0pt
* \skip\footins=10.0pt plus 4.0pt minus 2.0pt
* \hoffset=0.0pt
* \voffset=0.0pt
* \mag=1000
* \@twocolumnfalse
* \@twosidefalse
* \@mparswitchfalse
* \@reversemarginfalse
* (1in=72.27pt=25.4mm, 1cm=28.453pt)
(/usr/local/texlive/2025/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
[Loading MPS to PDF converter (version 2006.09.02).]
\scratchcounter=\count315
\scratchdimen=\dimen190
\scratchbox=\box59
\nofMPsegments=\count316
\nofMParguments=\count317
\everyMPshowfont=\toks29
\MPscratchCnt=\count318
\MPscratchDim=\dimen191
\MPnumerator=\count319
\makeMPintoPDFobject=\count320
\everyMPtoPDFconversion=\toks30
) (/usr/local/texlive/2025/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty
Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf
(/usr/local/texlive/2025/texmf-dist/tex/latex/grfext/grfext.sty
Package: grfext 2019/12/03 v1.3 Manage graphics extensions (HO)
)
Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4
85.
Package grfext Info: Graphics extension search list:
(grfext) [.pdf,.png,.jpg,.mps,.jpeg,.jbig2,.jb2,.PDF,.PNG,.JPG,.JPE
G,.JBIG2,.JB2,.eps]
(grfext) \AppendGraphicsExtensions on input line 504.
(/usr/local/texlive/2025/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
e
))
\c@lstlisting=\count321
Package hyperref Info: Link coloring OFF on input line 52.
(./report.out) (./report.out)
\@outlinefile=\write3
\openout3 = `report.out'.
Package caption Info: Begin \AtBeginDocument code.
Package caption Info: End \AtBeginDocument code.
LaTeX Font Info: Trying to load font information for U+msa on input line 55.
(/usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/umsa.fd
File: umsa.fd 2013/01/14 v3.01 AMS symbols A
)
LaTeX Font Info: Trying to load font information for U+msb on input line 55.
(/usr/local/texlive/2025/texmf-dist/tex/latex/amsfonts/umsb.fd
File: umsb.fd 2013/01/14 v3.01 AMS symbols B
)
[1
{/usr/local/texlive/2025/texmf-var/fonts/map/pdftex/updmap/pdftex.map}{/usr/loc
al/texlive/2025/texmf-dist/fonts/enc/dvips/cm-super/cm-super-t1.enc}{/usr/local
/texlive/2025/texmf-dist/fonts/enc/dvips/cm-super/cm-super-ts1.enc}]
LaTeX Font Info: Font shape `T1/cmtt/bx/n' in size <12> not available
(Font) Font shape `T1/cmtt/m/n' tried instead on input line 125.
LaTeX Font Info: Font shape `T1/cmtt/bx/n' in size <10> not available
(Font) Font shape `T1/cmtt/m/n' tried instead on input line 130.
[2]
Overfull \hbox (8.15242pt too wide) in paragraph at lines 148--149
\T1/cmr/m/n/10.95 ceives \T1/cmtt/m/n/10.95 next_uniform() \T1/cmr/m/n/10.95 an
d \T1/cmtt/m/n/10.95 generate_samples() \T1/cmr/m/n/10.95 for free. This is Rus
t's ap-proach to polymorphism---
[]
Package hyperref Info: bookmark level for unknown lstlisting defaults to 0 on i
nput line 177.
[3]
<good_lcg_histogram.png, id=210, 803.0pt x 602.25pt>
File: good_lcg_histogram.png Graphic file (type png)
<use good_lcg_histogram.png>
Package pdftex.def Info: good_lcg_histogram.png used on input line 238.
(pdftex.def) Requested size: 225.4804pt x 169.1067pt.
<randu_histogram.png, id=211, 803.0pt x 602.25pt>
File: randu_histogram.png Graphic file (type png)
<use randu_histogram.png>
Package pdftex.def Info: randu_histogram.png used on input line 243.
(pdftex.def) Requested size: 225.4804pt x 169.1067pt.
[4]
<good_lcg_3d.png, id=232, 1027.84pt x 770.88pt>
File: good_lcg_3d.png Graphic file (type png)
<use good_lcg_3d.png>
Package pdftex.def Info: good_lcg_3d.png used on input line 254.
(pdftex.def) Requested size: 225.4804pt x 169.10008pt.
<randu_3d.png, id=233, 1027.84pt x 770.88pt>
File: randu_3d.png Graphic file (type png)
<use randu_3d.png>
Package pdftex.def Info: randu_3d.png used on input line 259.
(pdftex.def) Requested size: 225.4804pt x 169.10008pt.
[5 <./good_lcg_histogram.png (PNG copy)> <./randu_histogram.png (PNG copy)> <./
good_lcg_3d.png (PNG copy)> <./randu_3d.png (PNG copy)>]
[6]
<lfsr_histogram.png, id=270, 803.0pt x 602.25pt>
File: lfsr_histogram.png Graphic file (type png)
<use lfsr_histogram.png>
Package pdftex.def Info: lfsr_histogram.png used on input line 348.
(pdftex.def) Requested size: 225.4804pt x 169.1067pt.
<lfsr_3d.png, id=271, 1027.84pt x 770.88pt>
File: lfsr_3d.png Graphic file (type png)
<use lfsr_3d.png>
Package pdftex.def Info: lfsr_3d.png used on input line 353.
(pdftex.def) Requested size: 225.4804pt x 169.10008pt.
[7 <./lfsr_histogram.png (PNG copy)> <./lfsr_3d.png (PNG copy)>]
[8]
<pcg32_histogram.png, id=346, 803.0pt x 602.25pt>
File: pcg32_histogram.png Graphic file (type png)
<use pcg32_histogram.png>
Package pdftex.def Info: pcg32_histogram.png used on input line 491.
(pdftex.def) Requested size: 225.4804pt x 169.1067pt.
<pcg32_3d.png, id=347, 1027.84pt x 770.88pt>
File: pcg32_3d.png Graphic file (type png)
<use pcg32_3d.png>
Package pdftex.def Info: pcg32_3d.png used on input line 496.
(pdftex.def) Requested size: 225.4804pt x 169.10008pt.
[9]
[10 <./pcg32_histogram.png (PNG copy)> <./pcg32_3d.png (PNG copy)>]
<rule30_histogram.png, id=396, 803.0pt x 602.25pt>
File: rule30_histogram.png Graphic file (type png)
<use rule30_histogram.png>
Package pdftex.def Info: rule30_histogram.png used on input line 586.
(pdftex.def) Requested size: 225.4804pt x 169.1067pt.
<rule30_3d.png, id=397, 1027.84pt x 770.88pt>
File: rule30_3d.png Graphic file (type png)
<use rule30_3d.png>
Package pdftex.def Info: rule30_3d.png used on input line 591.
(pdftex.def) Requested size: 225.4804pt x 169.10008pt.
[11]
[12 <./rule30_histogram.png (PNG copy)> <./rule30_3d.png (PNG copy)>]
(./src/lib.rs) (./src/lcg.rs
[13]) (./src/lfsr.rs
[14]) (./src/pcg.rs
[15]
[16]) (./src/rule30.rs
[17]) (./src/bin/problem1.rs
[18]
[19]
[20])
[21] (./src/bin/problem2.rs
[22]
[23]) (./src/bin/problem3.rs
[24]
[25]
[26]) (./src/bin/problem4.rs
[27]
[28]
[29])
[30] (./report.aux)
***********
LaTeX2e <2024-11-01> patch level 2
L3 programming layer <2025-01-18>
***********
Package rerunfilecheck Info: File `report.out' has not changed.
(rerunfilecheck) Checksum: E61EDB30162283142D52A71CE233CC6C;7696.
)
Here is how much of TeX's memory you used:
15601 strings out of 473190
238386 string characters out of 5715801
1065783 words of memory out of 5000000
37532 multiletter control sequences out of 15000+600000
576710 words of font info for 84 fonts, out of 8000000 for 9000
1141 hyphenation exceptions out of 8191
75i,8n,79p,379b,2148s stack positions out of 10000i,1000n,20000p,200000b,200000s
</usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb
></usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb>
</usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi8.pfb></
usr/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></us
r/local/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb></usr/l
ocal/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb></usr/lo
cal/texlive/2025/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy8.pfb></usr/loca
l/texlive/2025/texmf-dist/fonts/type1/public/cm-super/sfbx1095.pfb></usr/local/
texlive/2025/texmf-dist/fonts/type1/public/cm-super/sfbx1200.pfb></usr/local/te
xlive/2025/texmf-dist/fonts/type1/public/cm-super/sfbx1440.pfb></usr/local/texl
ive/2025/texmf-dist/fonts/type1/public/cm-super/sfit1000.pfb></usr/local/texliv
e/2025/texmf-dist/fonts/type1/public/cm-super/sfrm0600.pfb></usr/local/texlive/
2025/texmf-dist/fonts/type1/public/cm-super/sfrm1000.pfb></usr/local/texlive/20
25/texmf-dist/fonts/type1/public/cm-super/sfrm1095.pfb></usr/local/texlive/2025
/texmf-dist/fonts/type1/public/cm-super/sfrm1200.pfb></usr/local/texlive/2025/t
exmf-dist/fonts/type1/public/cm-super/sfrm1728.pfb></usr/local/texlive/2025/tex
mf-dist/fonts/type1/public/cm-super/sfti1095.pfb></usr/local/texlive/2025/texmf
-dist/fonts/type1/public/cm-super/sftt1000.pfb></usr/local/texlive/2025/texmf-d
ist/fonts/type1/public/cm-super/sftt1095.pfb></usr/local/texlive/2025/texmf-dis
t/fonts/type1/public/cm-super/sftt1200.pfb>
Output written on report.pdf (30 pages, 2832838 bytes).
PDF statistics:
1684 PDF objects out of 1728 (max. 8388607)
1585 compressed objects within 16 object streams
1120 named destinations out of 1200 (max. 500000)
331 words of extra memory for PDF output out of 10000 (max. 10000000)

View File

@ -0,0 +1,35 @@
\BOOKMARK [1][-]{section.1}{\376\377\000P\000r\000e\000a\000m\000b\000l\000e\000:\000\040\000I\000m\000p\000l\000e\000m\000e\000n\000t\000a\000t\000i\000o\000n\000\040\000i\000n\000\040\000R\000u\000s\000t}{}% 1
\BOOKMARK [2][-]{subsection.1.1}{\376\377\000W\000h\000y\000\040\000R\000u\000s\000t\000?}{section.1}% 2
\BOOKMARK [2][-]{subsection.1.2}{\376\377\000C\000o\000d\000e\000\040\000A\000r\000c\000h\000i\000t\000e\000c\000t\000u\000r\000e}{section.1}% 3
\BOOKMARK [2][-]{subsection.1.3}{\376\377\000T\000h\000e\000\040\000R\000a\000n\000d\000o\000m\000G\000e\000n\000e\000r\000a\000t\000o\000r\000\040\000T\000r\000a\000i\000t}{section.1}% 4
\BOOKMARK [2][-]{subsection.1.4}{\376\377\000K\000e\000y\000\040\000R\000u\000s\000t\000\040\000S\000y\000n\000t\000a\000x\000\040\000f\000o\000r\000\040\000N\000o\000n\000-\000R\000u\000s\000t\000a\000c\000e\000a\000n\000s}{section.1}% 5
\BOOKMARK [1][-]{section.2}{\376\377\000P\000r\000o\000b\000l\000e\000m\000\040\0001\000:\000\040\000L\000i\000n\000e\000a\000r\000\040\000C\000o\000n\000g\000r\000u\000e\000n\000t\000i\000a\000l\000\040\000G\000e\000n\000e\000r\000a\000t\000o\000r}{}% 6
\BOOKMARK [2][-]{subsection.2.1}{\376\377\000P\000a\000r\000t\000\040\000\050\000a\000\051\000:\000\040\000L\000C\000G\000\040\000I\000m\000p\000l\000e\000m\000e\000n\000t\000a\000t\000i\000o\000n}{section.2}% 7
\BOOKMARK [2][-]{subsection.2.2}{\376\377\000P\000a\000r\000t\000\040\000\050\000b\000\051\000:\000\040\000G\000o\000o\000d\000\040\000L\000C\000G\000\040\000v\000s\000\040\000R\000A\000N\000D\000U\000\040\000C\000o\000m\000p\000a\000r\000i\000s\000o\000n}{section.2}% 8
\BOOKMARK [3][-]{subsubsection.2.2.1}{\376\377\000S\000t\000a\000t\000i\000s\000t\000i\000c\000a\000l\000\040\000R\000e\000s\000u\000l\000t\000s}{subsection.2.2}% 9
\BOOKMARK [3][-]{subsubsection.2.2.2}{\376\377\000H\000i\000s\000t\000o\000g\000r\000a\000m\000s}{subsection.2.2}% 10
\BOOKMARK [3][-]{subsubsection.2.2.3}{\376\377\0003\000D\000\040\000S\000c\000a\000t\000t\000e\000r\000\040\000P\000l\000o\000t\000s}{subsection.2.2}% 11
\BOOKMARK [3][-]{subsubsection.2.2.4}{\376\377\000A\000n\000a\000l\000y\000s\000i\000s}{subsection.2.2}% 12
\BOOKMARK [1][-]{section.3}{\376\377\000P\000r\000o\000b\000l\000e\000m\000\040\0002\000:\000\040\000L\000i\000n\000e\000a\000r\000\040\000F\000e\000e\000d\000b\000a\000c\000k\000\040\000S\000h\000i\000f\000t\000\040\000R\000e\000g\000i\000s\000t\000e\000r\000\040\000\050\000X\000o\000r\000s\000h\000i\000f\000t\0003\0002\000\051}{}% 13
\BOOKMARK [2][-]{subsection.3.1}{\376\377\000P\000a\000r\000t\000\040\000\050\000a\000\051\000:\000\040\000X\000o\000r\000s\000h\000i\000f\000t\0003\0002\000\040\000I\000m\000p\000l\000e\000m\000e\000n\000t\000a\000t\000i\000o\000n}{section.3}% 14
\BOOKMARK [2][-]{subsection.3.2}{\376\377\000P\000a\000r\000t\000\040\000\050\000b\000\051\000:\000\040\000S\000t\000a\000t\000i\000s\000t\000i\000c\000a\000l\000\040\000A\000n\000a\000l\000y\000s\000i\000s}{section.3}% 15
\BOOKMARK [3][-]{subsubsection.3.2.1}{\376\377\000C\000o\000m\000p\000a\000r\000i\000s\000o\000n\000\040\000t\000o\000\040\000L\000C\000G}{subsection.3.2}% 16
\BOOKMARK [1][-]{section.4}{\376\377\000P\000r\000o\000b\000l\000e\000m\000\040\0003\000:\000\040\000P\000e\000r\000m\000u\000t\000e\000d\000\040\000C\000o\000n\000g\000r\000u\000e\000n\000t\000i\000a\000l\000\040\000G\000e\000n\000e\000r\000a\000t\000o\000r\000\040\000\050\000P\000C\000G\0003\0002\000\051}{}% 17
\BOOKMARK [2][-]{subsection.4.1}{\376\377\000P\000a\000r\000t\000\040\000\050\000a\000\051\000:\000\040\000A\000I\000-\000G\000e\000n\000e\000r\000a\000t\000e\000d\000\040\000C\000o\000d\000e\000\040\000w\000i\000t\000h\000\040\000A\000n\000n\000o\000t\000a\000t\000i\000o\000n\000s}{section.4}% 18
\BOOKMARK [2][-]{subsection.4.2}{\376\377\000U\000n\000d\000e\000r\000s\000t\000a\000n\000d\000i\000n\000g\000\040\000P\000C\000G\0003\0002}{section.4}% 19
\BOOKMARK [2][-]{subsection.4.3}{\376\377\000S\000t\000a\000t\000i\000s\000t\000i\000c\000a\000l\000\040\000R\000e\000s\000u\000l\000t\000s}{section.4}% 20
\BOOKMARK [1][-]{section.5}{\376\377\000P\000r\000o\000b\000l\000e\000m\000\040\0004\000:\000\040\000R\000u\000l\000e\000\040\0003\0000\000\040\000C\000e\000l\000l\000u\000l\000a\000r\000\040\000A\000u\000t\000o\000m\000a\000t\000o\000n}{}% 21
\BOOKMARK [2][-]{subsection.5.1}{\376\377\000P\000a\000r\000t\000\040\000\050\000a\000\051\000:\000\040\000R\000u\000l\000e\000\040\0003\0000\000\040\000I\000m\000p\000l\000e\000m\000e\000n\000t\000a\000t\000i\000o\000n}{section.5}% 22
\BOOKMARK [2][-]{subsection.5.2}{\376\377\000P\000a\000r\000t\000\040\000\050\000b\000\051\000:\000\040\000S\000t\000a\000t\000i\000s\000t\000i\000c\000a\000l\000\040\000A\000n\000a\000l\000y\000s\000i\000s}{section.5}% 23
\BOOKMARK [3][-]{subsubsection.5.2.1}{\376\377\000C\000o\000m\000p\000a\000r\000i\000s\000o\000n\000\040\000t\000o\000\040\000L\000C\000G\000\040\000a\000n\000d\000\040\000L\000F\000S\000R}{subsection.5.2}% 24
\BOOKMARK [1][-]{section.6}{\376\377\000S\000u\000m\000m\000a\000r\000y\000\040\000a\000n\000d\000\040\000C\000o\000n\000c\000l\000u\000s\000i\000o\000n\000s}{}% 25
\BOOKMARK [1][-]{appendix.A}{\376\377\000C\000o\000m\000p\000l\000e\000t\000e\000\040\000C\000o\000d\000e\000\040\000L\000i\000s\000t\000i\000n\000g\000s}{}% 26
\BOOKMARK [2][-]{subsection.A.1}{\376\377\000l\000i\000b\000.\000r\000s\000\040\040\023\000\040\000M\000a\000i\000n\000\040\000L\000i\000b\000r\000a\000r\000y\000\040\000w\000i\000t\000h\000\040\000T\000r\000a\000i\000t\000\040\000D\000e\000f\000i\000n\000i\000t\000i\000o\000n}{appendix.A}% 27
\BOOKMARK [2][-]{subsection.A.2}{\376\377\000l\000c\000g\000.\000r\000s\000\040\040\023\000\040\000L\000i\000n\000e\000a\000r\000\040\000C\000o\000n\000g\000r\000u\000e\000n\000t\000i\000a\000l\000\040\000G\000e\000n\000e\000r\000a\000t\000o\000r}{appendix.A}% 28
\BOOKMARK [2][-]{subsection.A.3}{\376\377\000l\000f\000s\000r\000.\000r\000s\000\040\040\023\000\040\000L\000i\000n\000e\000a\000r\000\040\000F\000e\000e\000d\000b\000a\000c\000k\000\040\000S\000h\000i\000f\000t\000\040\000R\000e\000g\000i\000s\000t\000e\000r}{appendix.A}% 29
\BOOKMARK [2][-]{subsection.A.4}{\376\377\000p\000c\000g\000.\000r\000s\000\040\040\023\000\040\000P\000e\000r\000m\000u\000t\000e\000d\000\040\000C\000o\000n\000g\000r\000u\000e\000n\000t\000i\000a\000l\000\040\000G\000e\000n\000e\000r\000a\000t\000o\000r}{appendix.A}% 30
\BOOKMARK [2][-]{subsection.A.5}{\376\377\000r\000u\000l\000e\0003\0000\000.\000r\000s\000\040\040\023\000\040\000R\000u\000l\000e\000\040\0003\0000\000\040\000C\000e\000l\000l\000u\000l\000a\000r\000\040\000A\000u\000t\000o\000m\000a\000t\000o\000n}{appendix.A}% 31
\BOOKMARK [2][-]{subsection.A.6}{\376\377\000p\000r\000o\000b\000l\000e\000m\0001\000.\000r\000s\000\040\040\023\000\040\000L\000C\000G\000\040\000A\000n\000a\000l\000y\000s\000i\000s\000\040\000P\000r\000o\000g\000r\000a\000m}{appendix.A}% 32
\BOOKMARK [2][-]{subsection.A.7}{\376\377\000p\000r\000o\000b\000l\000e\000m\0002\000.\000r\000s\000\040\040\023\000\040\000L\000F\000S\000R\000\040\000A\000n\000a\000l\000y\000s\000i\000s\000\040\000P\000r\000o\000g\000r\000a\000m}{appendix.A}% 33
\BOOKMARK [2][-]{subsection.A.8}{\376\377\000p\000r\000o\000b\000l\000e\000m\0003\000.\000r\000s\000\040\040\023\000\040\000P\000C\000G\0003\0002\000\040\000A\000n\000a\000l\000y\000s\000i\000s\000\040\000P\000r\000o\000g\000r\000a\000m}{appendix.A}% 34
\BOOKMARK [2][-]{subsection.A.9}{\376\377\000p\000r\000o\000b\000l\000e\000m\0004\000.\000r\000s\000\040\040\023\000\040\000R\000u\000l\000e\000\040\0003\0000\000\040\000A\000n\000a\000l\000y\000s\000i\000s\000\040\000P\000r\000o\000g\000r\000a\000m}{appendix.A}% 35

Binary file not shown.

View File

@ -0,0 +1,667 @@
\documentclass[11pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage{amsmath, amssymb}
\usepackage{graphicx}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{hyperref}
\usepackage{float}
\usepackage{booktabs}
\usepackage{caption}
\usepackage{subcaption}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
% Rust code styling
\definecolor{rustbg}{RGB}{248,248,248}
\definecolor{rustcomment}{RGB}{128,128,128}
\definecolor{rustkeyword}{RGB}{175,0,219}
\definecolor{ruststring}{RGB}{163,21,21}
\definecolor{rusttype}{RGB}{0,128,128}
\lstdefinelanguage{Rust}{
keywords={fn, let, mut, pub, struct, impl, self, Self, use, mod, for, in, if, else, return, match, true, false, as, const, where, trait},
keywordstyle=\color{rustkeyword}\bfseries,
ndkeywords={u64, u32, f64, bool, Vec, String, Option, Result, Box, usize, isize},
ndkeywordstyle=\color{rusttype},
comment=[l]{//},
morecomment=[s]{/*}{*/},
commentstyle=\color{rustcomment}\itshape,
stringstyle=\color{ruststring},
morestring=[b]",
sensitive=true,
showstringspaces=false,
basicstyle=\ttfamily\small,
backgroundcolor=\color{rustbg},
frame=single,
breaklines=true,
tabsize=4,
numbers=left,
numberstyle=\tiny\color{gray},
numbersep=5pt,
literate={}{{$\equiv$}}1,
}
\lstset{language=Rust}
\title{Homework 1: Random Number Generators\\
\large ME 2243 Bayesian Signal Processing}
\author{Dane Sabo}
\date{\today}
\begin{document}
\maketitle
%==============================================================================
\section*{AI Use Statement}
%==============================================================================
This homework was completed with the assistance of \textbf{Claude Code} (Anthropic's CLI tool for Claude), using the \textbf{Claude Opus 4.5} model.
\subsection*{How AI Was Used}
\begin{itemize}
\item \textbf{Learning Rust}: Claude helped explain Rust concepts like traits, ownership, and idiomatic patterns as I implemented the PRNGs. The explanations helped me understand \textit{why} certain approaches are preferred in Rust.
\item \textbf{Debugging}: When code didn't compile or produced unexpected results (e.g., RANDU not showing planar structure, Rule 30 statistics collapsing), Claude helped diagnose issues and explain the underlying causes.
\item \textbf{Plotting Code}: Claude wrote the \texttt{plotters} library boilerplate for generating histograms and 3D scatter plots, allowing me to focus on the PRNG algorithms themselves.
\item \textbf{PCG32 Implementation}: As specified in Problem 3, Claude generated the PCG32 code from a prompt. I then annotated the code with my own comments explaining each section.
\item \textbf{LaTeX Report}: Claude helped structure this report, filled in a
lot of the fluff including code formatting and organization.
\item \textbf{Mathematical Verification}: Claude suggested the mathematical verification of RANDU's planar constraint, demonstrating that $x_{n+2} \equiv 6x_{n+1} - 9x_n \pmod{2^{31}}$ holds for all triplets.
\end{itemize}
\subsection*{What I Did Myself}
\begin{itemize}
\item Implemented the LCG, LFSR (Xorshift), and Rule 30 algorithms based on the homework specifications
\item Designed the code architecture (trait-based polymorphism)
\item Annotated the PCG32 code with my own understanding
\item All analysis sections in this report
\end{itemize}
\hrule
\vspace{1em}
%==============================================================================
\section{Preamble: Implementation in Rust}
%==============================================================================
This homework was implemented in \textbf{Rust}, a systems programming language known for its memory safety, performance, and expressive type system. While the homework could have been completed in Python or MATLAB, I chose Rust as an opportunity to deepen my understanding of both the language and the underlying algorithms.
\subsection{Why Rust?}
Rust offers several advantages for implementing PRNGs:
\begin{itemize}
\item \textbf{Performance}: Rust compiles to native code, making bit operations and loops extremely fast
\item \textbf{Type Safety}: The compiler catches many errors at compile time
\item \textbf{Explicit Integer Types}: Rust has explicit \texttt{u32}, \texttt{u64} types, making bit-width considerations clear
\item \textbf{No Hidden Overflow}: Rust requires explicit handling of integer overflow via \texttt{wrapping\_mul}, \texttt{wrapping\_add}, etc.
\end{itemize}
\subsection{Code Architecture}
The code is organized as a Rust library with separate binary executables for each problem:
\begin{verbatim}
src/
lib.rs -- Trait definition and module exports
lcg.rs -- Linear Congruential Generator
lfsr.rs -- Linear Feedback Shift Register (Xorshift)
pcg.rs -- Permuted Congruential Generator
rule30.rs -- Rule 30 Cellular Automaton
bin/
problem1.rs -- LCG analysis and comparison
problem2.rs -- LFSR analysis
problem3.rs -- PCG32 analysis
problem4.rs -- Rule 30 analysis
\end{verbatim}
\subsection{The \texttt{RandomGenerator} Trait}
A key feature of Rust is \textbf{traits}, which define shared behavior across types (similar to interfaces in other languages). All PRNGs implement a common trait:
\begin{lstlisting}
pub trait RandomGenerator {
/// Generate the next random integer
fn next(&mut self) -> u64;
/// Return the modulus (range) of the generator
fn modulus(&self) -> u64;
// Default implementations provided for free:
fn next_uniform(&mut self) -> f64 {
self.next() as f64 / self.modulus() as f64
}
fn generate_samples(&mut self, n: u64) -> Vec<f64> {
(0..n).map(|_| self.next_uniform()).collect()
}
}
\end{lstlisting}
This means each PRNG only needs to implement \texttt{next()} and \texttt{modulus()}, and automatically receives \texttt{next\_uniform()} and \texttt{generate\_samples()} for free. This is Rust's approach to polymorphism---composition over inheritance.
\subsection{Key Rust Syntax for Non-Rustaceans}
For readers unfamiliar with Rust:
\begin{itemize}
\item \texttt{let mut x = 5;} -- Declare a mutable variable
\item \texttt{\&self} -- Borrow (read-only reference to) self
\item \texttt{\&mut self} -- Mutable borrow of self
\item \texttt{x.wrapping\_mul(y)} -- Multiply with wraparound on overflow
\item \texttt{x << n} -- Left bit shift by n positions
\item \texttt{x >> n} -- Right bit shift by n positions
\item \texttt{x \^{} y} -- XOR operation
\item \texttt{Vec<f64>} -- A dynamic array (vector) of 64-bit floats
\item \texttt{impl Trait for Type} -- Implement a trait for a specific type
\end{itemize}
%==============================================================================
\section{Problem 1: Linear Congruential Generator}
%==============================================================================
\subsection{Part (a): LCG Implementation}
The Linear Congruential Generator follows the recurrence relation:
\begin{align}
x_n &= (a \cdot x_{n-1} + c) \mod m \\
u_n &= x_n / m
\end{align}
\begin{lstlisting}[caption={LCG Implementation (src/lcg.rs)}]
pub struct Lcg {
state: u64,
a: u64, // multiplier
c: u64, // increment
m: u64, // modulus
}
impl Lcg {
pub fn new(seed: u64, a: u64, c: u64, m: u64) -> Self {
Lcg { state: seed, a, c, m }
}
}
impl RandomGenerator for Lcg {
fn next(&mut self) -> u64 {
self.state = (self.a.wrapping_mul(self.state)
.wrapping_add(self.c)) % self.m;
self.state
}
fn modulus(&self) -> u64 {
self.m
}
}
\end{lstlisting}
The \texttt{wrapping\_mul} and \texttt{wrapping\_add} functions handle potential integer overflow by wrapping around, which is the correct behavior for modular arithmetic.
\subsection{Part (b): Good LCG vs RANDU Comparison}
Two LCGs were compared:
\begin{itemize}
\item \textbf{Good LCG}: $a = 1664525$, $c = 1013904223$, $m = 2^{31}$
\item \textbf{RANDU}: $a = 65539$, $c = 0$, $m = 2^{31}$
\end{itemize}
\subsubsection{Statistical Results}
\begin{table}[H]
\centering
\begin{tabular}{lcc}
\toprule
\textbf{Metric} & \textbf{Good LCG} & \textbf{RANDU} \\
\midrule
Mean & 0.500304 & 0.502041 \\
Std Dev & 0.287667 & 0.287818 \\
Expected Mean & 0.5 & 0.5 \\
Expected Std Dev & 0.288675 & 0.288675 \\
\bottomrule
\end{tabular}
\caption{Statistical comparison of Good LCG and RANDU over 16,384 samples}
\end{table}
Both generators produce statistics very close to the expected values for a uniform distribution on $[0,1)$. The expected standard deviation is $\sqrt{1/12} \approx 0.2887$.
\subsubsection{Histograms}
\begin{figure}[H]
\centering
\begin{subfigure}[b]{0.48\textwidth}
\includegraphics[width=\textwidth]{good_lcg_histogram.png}
\caption{Good LCG}
\end{subfigure}
\hfill
\begin{subfigure}[b]{0.48\textwidth}
\includegraphics[width=\textwidth]{randu_histogram.png}
\caption{RANDU}
\end{subfigure}
\caption{Histograms of Good LCG and RANDU. Both appear uniformly distributed.}
\end{figure}
\subsubsection{3D Scatter Plots}
\begin{figure}[H]
\centering
\begin{subfigure}[b]{0.48\textwidth}
\includegraphics[width=\textwidth]{good_lcg_3d.png}
\caption{Good LCG -- uniform fill}
\end{subfigure}
\hfill
\begin{subfigure}[b]{0.48\textwidth}
\includegraphics[width=\textwidth]{randu_3d.png}
\caption{RANDU -- visible planar structure}
\end{subfigure}
\caption{3D scatter plots of consecutive triplets $(u_n, u_{n+1}, u_{n+2})$}
\end{figure}
\subsubsection{Analysis}
% TODO: DANE - Add your analysis here explaining:
% 1. What do you observe in the 3D plots?
% 2. Why does RANDU show planar structure while the good LCG fills space uniformly?
% 3. What are the implications for Monte Carlo simulations?
RANDU's failing is immediately clear from the 3D scatter plots. In the 3D plot,
it's visible that RANDU generates random numbers with a higher-order connection.
Any triplet of RANDU numbers will lie on one of 15 planes in the unit-cube. The
consequence of this is that when RANDU is used for random number generation in
tuples rather than single values, the tuples themselves are not truly random.
\paragraph{Mathematical Verification (Claude Aside):} During development, the AI assistant suggested a mathematical verification of RANDU's planar structure. Every triplet of consecutive RANDU values satisfies the linear constraint:
\[
x_{n+2} \equiv 6 \cdot x_{n+1} - 9 \cdot x_n \pmod{2^{31}}
\]
This was verified programmatically:
\begin{verbatim}
Triplet 0: x2=1769499, 6*x1-9*x0 (mod 2^31)=1769499, Match: true
Triplet 1: x2=7077969, 6*x1-9*x0 (mod 2^31)=7077969, Match: true
Triplet 2: x2=26542323, 6*x1-9*x0 (mod 2^31)=26542323, Match: true
\end{verbatim}
This algebraic constraint means that knowing any two consecutive values completely determines the third, which is why the points lie on planes defined by this linear equation.
%==============================================================================
\section{Problem 2: Linear Feedback Shift Register (Xorshift32)}
%==============================================================================
\subsection{Part (a): Xorshift32 Implementation}
The Xorshift32 algorithm uses XOR and bit shift operations to generate pseudo-random numbers:
\begin{align}
x &\leftarrow x \oplus (x \ll a) \\
x &\leftarrow x \oplus (x \gg b) \\
x &\leftarrow x \oplus (x \ll c)
\end{align}
with parameters $a = 13$, $b = 17$, $c = 5$.
\begin{lstlisting}[caption={LFSR/Xorshift Implementation (src/lfsr.rs)}]
pub struct Lfsr {
state: u32,
a: u32,
b: u32,
c: u32,
m: u32,
}
impl RandomGenerator for Lfsr {
fn next(&mut self) -> u64 {
self.state = self.state ^ (self.state << self.a);
self.state = self.state ^ (self.state >> self.b);
self.state = self.state ^ (self.state << self.c);
self.state as u64
}
fn modulus(&self) -> u64 {
self.m as u64
}
}
\end{lstlisting}
The three XOR-shift operations create complex bit mixing. Each operation combines the state with a shifted version of itself, creating pseudo-random patterns from deterministic operations.
\subsection{Part (b): Statistical Analysis}
\begin{table}[H]
\centering
\begin{tabular}{lcc}
\toprule
\textbf{Metric} & \textbf{Xorshift32} & \textbf{Expected} \\
\midrule
Mean & 0.499617 & 0.5 \\
Std Dev & 0.288751 & 0.288675 \\
\bottomrule
\end{tabular}
\caption{Xorshift32 statistics over 100,000 samples}
\end{table}
\begin{figure}[H]
\centering
\begin{subfigure}[b]{0.48\textwidth}
\includegraphics[width=\textwidth]{lfsr_histogram.png}
\caption{Histogram}
\end{subfigure}
\hfill
\begin{subfigure}[b]{0.48\textwidth}
\includegraphics[width=\textwidth]{lfsr_3d.png}
\caption{3D Scatter Plot}
\end{subfigure}
\caption{Xorshift32 analysis showing uniform distribution and no visible correlation structure}
\end{figure}
\subsubsection{Comparison to LCG}
% TODO: DANE - Add your comparison here:
% 1. How does the 3D scatter plot compare to the Good LCG and RANDU?
% 2. What advantages does Xorshift have over LCG?
% 3. Discuss speed vs. quality tradeoffs
LFSR produces an indistinguishable result to the LCG random number generator
with no clear bias. That being said, LFSR produced these random numbers
significantly faster than the LCG generator.
%==============================================================================
\section{Problem 3: Permuted Congruential Generator (PCG32)}
%==============================================================================
\subsection{Part (a): AI-Generated Code with Annotations}
Per the homework instructions, the following code was generated using Claude Code with the prompt: \textit{``Write code to implement PCG32 in my favorite programming language (Rust!)''}
The annotations (comments starting with \texttt{// DAS}) are my own explanations of what each part of the code does.
\begin{lstlisting}[caption={PCG32 Implementation with Annotations (src/pcg.rs)}]
// DAS COMMENT:
// The prompt for creating this code was verbatim: "Write code to
// implement PCG32 in my favorite programming language (Rust!)"
// This was generated using a Claude Code session.
pub struct Pcg32 {
state: u64, // Internal LCG state (64-bit)
increment: u64, // Must be odd
}
impl Pcg32 {
// Standard PCG32 parameters
const MULTIPLIER: u64 = 6364136223846793005;
const DEFAULT_INCREMENT: u64 = 1442695040888963407;
pub fn new(seed: u64) -> Self {
// DAS - Any new instance immediately runs through
// new_with_increment with default increment
Pcg32::new_with_increment(seed, Self::DEFAULT_INCREMENT)
}
pub fn new_with_increment(seed: u64, increment: u64) -> Self {
let mut pcg = Pcg32 {
state: 0,
increment: (increment << 1) | 1,
// DAS - Ensures increment is always odd by:
// 1. Shifting left by 1 (multiplies by 2, making LSB=0)
// 2. OR with 1 (sets LSB=1, guaranteeing odd)
};
// DAS - This is the initialization sequence.
// Claude skipped step 3 from the homework (the first LCG step
// before adding seed). It adds seed to state, then steps.
pcg.state = pcg.state.wrapping_add(seed);
pcg.step();
pcg
}
fn step(&mut self) {
// DAS - This is a standard LCG step:
// state = state * multiplier + increment
self.state = self.state
.wrapping_mul(Self::MULTIPLIER)
.wrapping_add(self.increment);
}
fn output(state: u64) -> u32 {
// XOR high and low parts
let xorshifted = (((state >> 18) ^ state) >> 27) as u32;
let rot = (state >> 59) as u32;
// DAS - The homework says "Return (xorshifted >> rot)" but
// that would pad zeros, not truly rotate. Claude correctly
// uses rotate_right() for a proper bit rotation.
xorshifted.rotate_right(rot)
}
}
impl RandomGenerator for Pcg32 {
fn next(&mut self) -> u64 {
let old_state = self.state;
self.step();
// DAS - This matches the homework exactly:
// 1. Save old state
// 2. Advance state (LCG step)
// 3. Output permutation of OLD state
Self::output(old_state) as u64
}
fn modulus(&self) -> u64 {
u32::MAX as u64
}
}
\end{lstlisting}
\subsection{Understanding PCG32}
PCG32 combines two concepts:
\begin{enumerate}
\item \textbf{LCG for state advancement}: The internal 64-bit state advances using a standard LCG with a carefully chosen multiplier. This provides the period ($2^{64}$) and determines the sequence.
\item \textbf{Output permutation (XSH-RR)}: The output is derived by applying a permutation function to the state:
\begin{itemize}
\item \textbf{XSH} (Xorshift High): \texttt{((state >> 18) \^{} state) >> 27} mixes the high bits with the low bits
\item \textbf{RR} (Random Rotation): The result is rotated by an amount determined by the high 5 bits of the state
\end{itemize}
\end{enumerate}
The key insight is that while the LCG state has predictable low bits (they cycle with small periods), the permutation function extracts randomness from the high-quality high bits while using the state itself to determine how to scramble the output.
\subsection{Statistical Results}
\begin{table}[H]
\centering
\begin{tabular}{lcc}
\toprule
\textbf{Metric} & \textbf{PCG32} & \textbf{Expected} \\
\midrule
Mean & 0.498255 & 0.5 \\
Std Dev & 0.288584 & 0.288675 \\
\bottomrule
\end{tabular}
\caption{PCG32 statistics over 100,000 samples}
\end{table}
\begin{figure}[H]
\centering
\begin{subfigure}[b]{0.48\textwidth}
\includegraphics[width=\textwidth]{pcg32_histogram.png}
\caption{Histogram}
\end{subfigure}
\hfill
\begin{subfigure}[b]{0.48\textwidth}
\includegraphics[width=\textwidth]{pcg32_3d.png}
\caption{3D Scatter Plot}
\end{subfigure}
\caption{PCG32 analysis showing excellent statistical properties (<- Claude is
proud of itself)}
\end{figure}
%==============================================================================
\section{Problem 4: Rule 30 Cellular Automaton}
%==============================================================================
\subsection{Part (a): Rule 30 Implementation}
Rule 30 is an elementary cellular automaton where each cell's next state depends on its current state and its two neighbors:
\begin{table}[H]
\centering
\begin{tabular}{c|cccccccc}
\textbf{Configuration} & 111 & 110 & 101 & 100 & 011 & 010 & 001 & 000 \\
\hline
\textbf{New State} & 0 & 0 & 0 & 1 & 1 & 1 & 1 & 0 \\
\end{tabular}
\caption{Rule 30 transition table (binary: 00011110 = 30 in decimal)}
\end{table}
\begin{lstlisting}[caption={Rule 30 Implementation (src/rule30.rs)}]
pub struct Rule30 {
state: u32, // 32 cells packed into a single u32
}
impl Rule30 {
pub fn new(seed: u32) -> Self {
// Initialize with seed; if 0, use single bit in center
let initial_state = if seed == 0 { 1 << 16 } else { seed };
Rule30 { state: initial_state }
}
// Apply Rule 30 with periodic boundary conditions
// Uses bitwise operations on all 32 cells simultaneously
fn step(&mut self) {
// For Rule 30: new_cell = left XOR (center OR right)
let left = self.state.rotate_right(1); // Wrap right
let center = self.state;
let right = self.state.rotate_left(1); // Wrap left
// Rule 30: output = left XOR (center OR right)
self.state = left ^ (center | right);
}
}
impl RandomGenerator for Rule30 {
fn next(&mut self) -> u64 {
self.step(); // Advance one generation
self.state as u64 // Entire 32-bit state IS the number
}
fn modulus(&self) -> u64 {
(u32::MAX as u64) + 1 // 2^32
}
}
\end{lstlisting}
\textbf{Key Implementation Details:}
\begin{itemize}
\item \textbf{32 cells} as specified in the homework, packed into a single \texttt{u32}
\item \textbf{Periodic boundary conditions} via \texttt{rotate\_left/right}, creating a circular topology
\item \textbf{Bitwise operations} apply Rule 30 to all 32 cells simultaneously---extremely fast!
\item \textbf{Output method}: Each generation, the entire 32-bit state is read as the random number, matching the homework formula: $u = \sum_{b=1}^{32} s_b \cdot 2^{-b}$
\end{itemize}
The elegant insight is that Rule 30's update formula $\text{new} = \text{left} \oplus (\text{center} \lor \text{right})$ can be applied to all 32 cells in parallel using bitwise operations.
\subsection{Part (b): Statistical Analysis}
\begin{table}[H]
\centering
\begin{tabular}{lcc}
\toprule
\textbf{Metric} & \textbf{Rule 30} & \textbf{Expected} \\
\midrule
Mean & 0.500579 & 0.5 \\
Std Dev & 0.289578 & 0.288675 \\
\bottomrule
\end{tabular}
\caption{Rule 30 statistics over 100,000 samples (32-cell implementation)}
\end{table}
\begin{figure}[H]
\centering
\begin{subfigure}[b]{0.48\textwidth}
\includegraphics[width=\textwidth]{rule30_histogram.png}
\caption{Histogram}
\end{subfigure}
\hfill
\begin{subfigure}[b]{0.48\textwidth}
\includegraphics[width=\textwidth]{rule30_3d.png}
\caption{3D Scatter Plot}
\end{subfigure}
\caption{Rule 30 analysis showing good statistical properties}
\end{figure}
\subsubsection{Comparison to LCG and LFSR}
% TODO: DANE - Add your comparison here:
% 1. How does Rule 30's 3D plot compare to the other generators?
% 2. What are the tradeoffs of using a cellular automaton vs. algebraic methods?
% 3. Why did Wolfram choose Rule 30 for Mathematica's random number generator?
% 4. Discuss computational cost vs. randomness quality
Rule30 can be extremely fast when implemented on something like a gate array.
Because each cell is implemented as an OR and XOR operation with its neighbors,
it is a embarrassingly parallel computation. Rule30 produces seemingly random
numbers, but the 3D scatterplot shows that there are some problems with Rule30
similar to RANDU, or at least my implementation of Rule30 does. There is not
even coverage of the space.
%==============================================================================
\section{Summary and Conclusions}
%==============================================================================
Listed is a summary of the performance of each PRNG.
\begin{table}[H]
\centering
\begin{tabular}{lcccl}
\toprule
\textbf{Generator} & \textbf{Mean} & \textbf{Std Dev} & \textbf{3D Structure} & \textbf{Notes} \\
\midrule
Good LCG & 0.500 & 0.288 & Uniform & Simple, fast \\
RANDU & 0.502 & 0.288 & \textbf{15 planes!} & Catastrophically flawed \\
Xorshift32 & 0.500 & 0.289 & Uniform & Fast, good quality \\
PCG32 & 0.498 & 0.289 & Uniform & Modern, excellent quality \\
Rule 30 & 0.501 & 0.290 & Uniform & Fast (bitwise on u32) \\
\bottomrule
\end{tabular}
\caption{Summary comparison of all implemented PRNGs}
\end{table}
%==============================================================================
\newpage
\appendix
\section{Complete Code Listings}
%==============================================================================
\subsection{lib.rs -- Main Library with Trait Definition}
\lstinputlisting[language=Rust]{src/lib.rs}
\subsection{lcg.rs -- Linear Congruential Generator}
\lstinputlisting[language=Rust]{src/lcg.rs}
\subsection{lfsr.rs -- Linear Feedback Shift Register}
\lstinputlisting[language=Rust]{src/lfsr.rs}
\subsection{pcg.rs -- Permuted Congruential Generator}
\lstinputlisting[language=Rust]{src/pcg.rs}
\subsection{rule30.rs -- Rule 30 Cellular Automaton}
\lstinputlisting[language=Rust]{src/rule30.rs}
\subsection{problem1.rs -- LCG Analysis Program}
\lstinputlisting[language=Rust]{src/bin/problem1.rs}
\subsection{problem2.rs -- LFSR Analysis Program}
\lstinputlisting[language=Rust]{src/bin/problem2.rs}
\subsection{problem3.rs -- PCG32 Analysis Program}
\lstinputlisting[language=Rust]{src/bin/problem3.rs}
\subsection{problem4.rs -- Rule 30 Analysis Program}
\lstinputlisting[language=Rust]{src/bin/problem4.rs}
\end{document}

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@ -0,0 +1,167 @@
use statrs::statistics::{Data, Distribution};
use solutions::{RandomGenerator, Lcg};
use plotters::prelude::*;
fn plot_histogram(
samples: &[f64],
filename: &str,
title: &str,
bins: usize,
) -> Result<(), Box<dyn std::error::Error>> {
// Create histogram bins
let mut counts = vec![0u32; bins];
for &sample in samples {
let bin = ((sample * bins as f64).floor() as usize).min(bins - 1);
counts[bin] += 1;
}
let max_count = *counts.iter().max().unwrap() as f64;
// Set up the drawing area
let root = BitMapBackend::new(filename, (800, 600)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption(title, ("sans-serif", 30))
.margin(10)
.x_label_area_size(40)
.y_label_area_size(50)
.build_cartesian_2d(0.0..1.0, 0.0..(max_count * 1.1))?;
chart
.configure_mesh()
.x_desc("Value")
.y_desc("Count")
.draw()?;
// Draw histogram bars
chart.draw_series(
counts.iter().enumerate().map(|(i, &count)| {
let x0 = i as f64 / bins as f64;
let x1 = (i + 1) as f64 / bins as f64;
Rectangle::new([(x0, 0.0), (x1, count as f64)], BLUE.mix(0.6).filled())
}),
)?;
root.present()?;
println!("Histogram saved to: {}", filename);
Ok(())
}
fn plot_3d_scatter(
samples: &[f64],
filename: &str,
title: &str,
max_points: usize,
) -> Result<(), Box<dyn std::error::Error>> {
// Create triplets from consecutive samples
let triplets: Vec<(f64, f64, f64)> = samples
.windows(3)
.step_by(1)
.take(max_points)
.map(|w| (w[0], w[1], w[2]))
.collect();
// Set up the drawing area
let root = BitMapBackend::new(filename, (1024, 768)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption(title, ("sans-serif", 30))
.margin(10)
.build_cartesian_3d(0.0..1.0, 0.0..1.0, 0.0..1.0)?;
// Rotate the view to better see planar structure
chart.with_projection(|mut pb| {
pb.pitch = 0.8; // Tilt up/down
pb.yaw = 0.5; // Rotate left/right
pb.scale = 0.9;
pb.into_matrix()
});
chart.configure_axes().draw()?;
// Draw the points
chart.draw_series(
triplets
.iter()
.map(|&(x, y, z)| Circle::new((x, y, z), 2, BLUE.filled())),
)?;
root.present()?;
println!("Plot saved to: {}", filename);
Ok(())
}
fn main() {
let monsanto = 1; // repeatable seed
//
// Problem 1: Linear Congruential Generator
// Part a
let mut garbage_lcg = Lcg::new(monsanto, 7, 1737753, 1 << 31);
println!("PROBLEM 1:");
println!("__________");
println!("Part a)");
for i in 0..5 {
println!("Random Number {}: {}", i, garbage_lcg.next_uniform())
}
println!("Part B)");
let mut good_lcg = Lcg::new(monsanto, 1_664_525, 1_013_904_223, 1 << 31);
let mut randu = Lcg::new(monsanto, 65_539, 0, 1 << 31); // RANDU: a=65539, c=0, m=2^31
let n = 2 << 13;
let good_lcg_samples = good_lcg.generate_samples(n);
let randu_samples = randu.generate_samples(n);
let good_lcg_data = Data::new(good_lcg_samples.clone());
let randu_data = Data::new(randu_samples.clone());
println!("Good LCG Mean: {:6}", good_lcg_data.mean().unwrap());
println!("RANDU Mean: {:6}", randu_data.mean().unwrap());
println!("Good LCG STD Dev: {:6}", good_lcg_data.std_dev().unwrap());
println!("RANDU STD Dev: {:6}", randu_data.std_dev().unwrap());
// Generate histograms
println!("\nGenerating histograms...");
plot_histogram(&good_lcg_samples, "good_lcg_histogram.png", "Good LCG - Histogram", 50)
.expect("Failed to create Good LCG histogram");
plot_histogram(&randu_samples, "randu_histogram.png", "RANDU - Histogram", 50)
.expect("Failed to create RANDU histogram");
// Generate fresh samples for 3D plotting
println!("\nGenerating 3D scatter plots...");
let good_lcg_samples = good_lcg.generate_samples(30000);
let randu_samples = randu.generate_samples(30000);
// Create 3D scatter plots with more points
plot_3d_scatter(&good_lcg_samples, "good_lcg_3d.png", "Good LCG - 3D Scatter", 10000)
.expect("Failed to create Good LCG plot");
plot_3d_scatter(&randu_samples, "randu_3d.png", "RANDU - 3D Scatter (Shows Planar Structure)", 10000)
.expect("Failed to create RANDU plot");
// Verify RANDU planar structure mathematically
// For RANDU: x_{n+2} ≡ 6*x_{n+1} - 9*x_n (mod 2^31)
println!("\nVerifying RANDU planar structure:");
let test_triplets: Vec<(u64, u64, u64)> = {
let mut test_randu = Lcg::new(monsanto, 65_539, 0, 1 << 31);
let samples: Vec<u64> = (0..100).map(|_| test_randu.next()).collect();
samples.windows(3).map(|w| (w[0], w[1], w[2])).take(10).collect()
};
let m = 1u64 << 31;
for (i, &(x0, x1, x2)) in test_triplets.iter().enumerate() {
let expected = (6 * x1 + m - (9 * x0) % m) % m;
let matches = x2 == expected;
if i < 3 { // Show first 3
println!(" Triplet {}: x2={}, 6*x1-9*x0 (mod 2^31)={}, Match: {}",
i, x2, expected, matches);
}
}
}

View File

@ -0,0 +1,145 @@
use statrs::statistics::{Data, Distribution};
use solutions::{RandomGenerator, Lfsr};
use plotters::prelude::*;
fn plot_histogram(
samples: &[f64],
filename: &str,
title: &str,
bins: usize,
) -> Result<(), Box<dyn std::error::Error>> {
// Create histogram bins
let mut counts = vec![0u32; bins];
for &sample in samples {
let bin = ((sample * bins as f64).floor() as usize).min(bins - 1);
counts[bin] += 1;
}
let max_count = *counts.iter().max().unwrap() as f64;
// Set up the drawing area
let root = BitMapBackend::new(filename, (800, 600)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption(title, ("sans-serif", 30))
.margin(10)
.x_label_area_size(40)
.y_label_area_size(50)
.build_cartesian_2d(0.0..1.0, 0.0..(max_count * 1.1))?;
chart
.configure_mesh()
.x_desc("Value")
.y_desc("Count")
.draw()?;
// Draw histogram bars
chart.draw_series(
counts.iter().enumerate().map(|(i, &count)| {
let x0 = i as f64 / bins as f64;
let x1 = (i + 1) as f64 / bins as f64;
Rectangle::new([(x0, 0.0), (x1, count as f64)], BLUE.mix(0.6).filled())
}),
)?;
root.present()?;
println!("Histogram saved to: {}", filename);
Ok(())
}
fn plot_3d_scatter(
samples: &[f64],
filename: &str,
title: &str,
max_points: usize,
) -> Result<(), Box<dyn std::error::Error>> {
// Create triplets from consecutive samples
let triplets: Vec<(f64, f64, f64)> = samples
.windows(3)
.step_by(1)
.take(max_points)
.map(|w| (w[0], w[1], w[2]))
.collect();
// Set up the drawing area
let root = BitMapBackend::new(filename, (1024, 768)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption(title, ("sans-serif", 30))
.margin(10)
.build_cartesian_3d(0.0..1.0, 0.0..1.0, 0.0..1.0)?;
// Rotate the view to better see structure
chart.with_projection(|mut pb| {
pb.pitch = 0.8;
pb.yaw = 0.5;
pb.scale = 0.9;
pb.into_matrix()
});
chart.configure_axes().draw()?;
// Draw the points
chart.draw_series(
triplets
.iter()
.map(|&(x, y, z)| Circle::new((x, y, z), 2, BLUE.filled())),
)?;
root.present()?;
println!("Plot saved to: {}", filename);
Ok(())
}
fn main() {
println!("PROBLEM 2: LFSR (Xorshift)");
println!("===========================");
// LFSR parameters: a=13, b=17, c=5
let seed = 1;
let a = 13;
let b = 17;
let c = 5;
let m = u32::MAX; // Maximum value for u32
let mut lfsr = Lfsr::new(seed, a, b, c, m);
println!("Parameters: a={}, b={}, c={}, m=2^32-1", a, b, c);
println!("Seed: {}\n", seed);
// Generate first few samples to show output
println!("First 5 random numbers:");
for i in 0..5 {
println!(" Random Number {}: {:.10}", i, lfsr.next_uniform());
}
// Generate large number of samples for statistics
let n = 100_000;
println!("\nGenerating {} samples for analysis...", n);
let samples = lfsr.generate_samples(n);
let data = Data::new(samples.clone());
// Calculate statistics
let mean = data.mean().unwrap();
let std_dev = data.std_dev().unwrap();
println!("\nStatistics:");
println!(" Mean: {:.6} (expected: 0.5)", mean);
println!(" Std Dev: {:.6} (expected: {:.6})", std_dev, (1.0/12.0_f64).sqrt());
// Generate histogram
println!("\nGenerating histogram...");
plot_histogram(&samples, "lfsr_histogram.png", "LFSR (Xorshift) - Histogram", 50)
.expect("Failed to create histogram");
// Generate 3D scatter plot
println!("Generating 3D scatter plot...");
let plot_samples = lfsr.generate_samples(30000);
plot_3d_scatter(&plot_samples, "lfsr_3d.png", "LFSR (Xorshift) - 3D Scatter", 10000)
.expect("Failed to create 3D scatter plot");
println!("\nDone! Check the generated PNG files.");
}

View File

@ -0,0 +1,142 @@
use statrs::statistics::{Data, Distribution};
use solutions::{RandomGenerator, Pcg32};
use plotters::prelude::*;
fn plot_histogram(
samples: &[f64],
filename: &str,
title: &str,
bins: usize,
) -> Result<(), Box<dyn std::error::Error>> {
// Create histogram bins
let mut counts = vec![0u32; bins];
for &sample in samples {
let bin = ((sample * bins as f64).floor() as usize).min(bins - 1);
counts[bin] += 1;
}
let max_count = *counts.iter().max().unwrap() as f64;
// Set up the drawing area
let root = BitMapBackend::new(filename, (800, 600)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption(title, ("sans-serif", 30))
.margin(10)
.x_label_area_size(40)
.y_label_area_size(50)
.build_cartesian_2d(0.0..1.0, 0.0..(max_count * 1.1))?;
chart
.configure_mesh()
.x_desc("Value")
.y_desc("Count")
.draw()?;
// Draw histogram bars
chart.draw_series(
counts.iter().enumerate().map(|(i, &count)| {
let x0 = i as f64 / bins as f64;
let x1 = (i + 1) as f64 / bins as f64;
Rectangle::new([(x0, 0.0), (x1, count as f64)], BLUE.mix(0.6).filled())
}),
)?;
root.present()?;
println!("Histogram saved to: {}", filename);
Ok(())
}
fn plot_3d_scatter(
samples: &[f64],
filename: &str,
title: &str,
max_points: usize,
) -> Result<(), Box<dyn std::error::Error>> {
// Create triplets from consecutive samples
let triplets: Vec<(f64, f64, f64)> = samples
.windows(3)
.step_by(1)
.take(max_points)
.map(|w| (w[0], w[1], w[2]))
.collect();
// Set up the drawing area
let root = BitMapBackend::new(filename, (1024, 768)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption(title, ("sans-serif", 30))
.margin(10)
.build_cartesian_3d(0.0..1.0, 0.0..1.0, 0.0..1.0)?;
// Rotate the view
chart.with_projection(|mut pb| {
pb.pitch = 0.8;
pb.yaw = 0.5;
pb.scale = 0.9;
pb.into_matrix()
});
chart.configure_axes().draw()?;
// Draw the points
chart.draw_series(
triplets
.iter()
.map(|&(x, y, z)| Circle::new((x, y, z), 2, BLUE.filled())),
)?;
root.present()?;
println!("Plot saved to: {}", filename);
Ok(())
}
fn main() {
println!("PROBLEM 3: PCG32 (Permuted Congruential Generator)");
println!("===================================================");
println!("PCG32 is a modern PRNG with excellent statistical properties.");
println!("It uses a 64-bit LCG internally with output permutation (XSH-RR).\n");
let seed = 42; // Classic seed choice!
let mut pcg = Pcg32::new(seed);
println!("Seed: {}\n", seed);
// Generate first few samples to show output
println!("First 5 random numbers:");
for i in 0..5 {
println!(" Random Number {}: {:.10}", i, pcg.next_uniform());
}
// Generate large number of samples for statistics
let n = 100_000;
println!("\nGenerating {} samples for analysis...", n);
let samples = pcg.generate_samples(n);
let data = Data::new(samples.clone());
// Calculate statistics
let mean = data.mean().unwrap();
let std_dev = data.std_dev().unwrap();
println!("\nStatistics:");
println!(" Mean: {:.6} (expected: 0.5)", mean);
println!(" Std Dev: {:.6} (expected: {:.6})", std_dev, (1.0/12.0_f64).sqrt());
// Generate histogram
println!("\nGenerating histogram...");
plot_histogram(&samples, "pcg32_histogram.png", "PCG32 - Histogram", 50)
.expect("Failed to create histogram");
// Generate 3D scatter plot
println!("Generating 3D scatter plot...");
let plot_samples = pcg.generate_samples(30000);
plot_3d_scatter(&plot_samples, "pcg32_3d.png", "PCG32 - 3D Scatter", 10000)
.expect("Failed to create 3D scatter plot");
println!("\nDone! Check the generated PNG files.");
println!("\nNote: PCG32 should show excellent uniformity and no visible");
println!("correlation patterns in the 3D plot - much better than basic LCGs!");
}

View File

@ -0,0 +1,143 @@
use statrs::statistics::{Data, Distribution};
use solutions::{RandomGenerator, Rule30};
use plotters::prelude::*;
fn plot_histogram(
samples: &[f64],
filename: &str,
title: &str,
bins: usize,
) -> Result<(), Box<dyn std::error::Error>> {
// Create histogram bins
let mut counts = vec![0u32; bins];
for &sample in samples {
let bin = ((sample * bins as f64).floor() as usize).min(bins - 1);
counts[bin] += 1;
}
let max_count = *counts.iter().max().unwrap() as f64;
// Set up the drawing area
let root = BitMapBackend::new(filename, (800, 600)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption(title, ("sans-serif", 30))
.margin(10)
.x_label_area_size(40)
.y_label_area_size(50)
.build_cartesian_2d(0.0..1.0, 0.0..(max_count * 1.1))?;
chart
.configure_mesh()
.x_desc("Value")
.y_desc("Count")
.draw()?;
// Draw histogram bars
chart.draw_series(
counts.iter().enumerate().map(|(i, &count)| {
let x0 = i as f64 / bins as f64;
let x1 = (i + 1) as f64 / bins as f64;
Rectangle::new([(x0, 0.0), (x1, count as f64)], BLUE.mix(0.6).filled())
}),
)?;
root.present()?;
println!("Histogram saved to: {}", filename);
Ok(())
}
fn plot_3d_scatter(
samples: &[f64],
filename: &str,
title: &str,
max_points: usize,
) -> Result<(), Box<dyn std::error::Error>> {
// Create triplets from consecutive samples
let triplets: Vec<(f64, f64, f64)> = samples
.windows(3)
.step_by(1)
.take(max_points)
.map(|w| (w[0], w[1], w[2]))
.collect();
// Set up the drawing area
let root = BitMapBackend::new(filename, (1024, 768)).into_drawing_area();
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption(title, ("sans-serif", 30))
.margin(10)
.build_cartesian_3d(0.0..1.0, 0.0..1.0, 0.0..1.0)?;
// Rotate the view
chart.with_projection(|mut pb| {
pb.pitch = 0.8;
pb.yaw = 0.5;
pb.scale = 0.9;
pb.into_matrix()
});
chart.configure_axes().draw()?;
// Draw the points
chart.draw_series(
triplets
.iter()
.map(|&(x, y, z)| Circle::new((x, y, z), 2, BLUE.filled())),
)?;
root.present()?;
println!("Plot saved to: {}", filename);
Ok(())
}
fn main() {
println!("PROBLEM 4: Rule 30 Cellular Automaton");
println!("======================================");
println!("Rule 30 is an elementary cellular automaton discovered by Stephen Wolfram.");
println!("Uses 32 cells with periodic boundaries; each state IS the 32-bit random number.\n");
let seed = 42u32;
let mut rule30 = Rule30::new(seed);
println!("Seed: {}", seed);
println!("Cells: 32 (packed as u32)\n");
// Generate first few samples to show output
println!("First 5 random numbers:");
for i in 0..5 {
println!(" Random Number {}: {:.10}", i, rule30.next_uniform());
}
// Generate large number of samples for statistics
let n = 100_000;
println!("\nGenerating {} samples for analysis...", n);
let samples = rule30.generate_samples(n);
let data = Data::new(samples.clone());
// Calculate statistics
let mean = data.mean().unwrap();
let std_dev = data.std_dev().unwrap();
println!("\nStatistics:");
println!(" Mean: {:.6} (expected: 0.5)", mean);
println!(" Std Dev: {:.6} (expected: {:.6})", std_dev, (1.0/12.0_f64).sqrt());
// Generate histogram
println!("\nGenerating histogram...");
plot_histogram(&samples, "rule30_histogram.png", "Rule 30 - Histogram", 50)
.expect("Failed to create histogram");
// Generate 3D scatter plot
println!("Generating 3D scatter plot...");
let plot_samples = rule30.generate_samples(30000);
plot_3d_scatter(&plot_samples, "rule30_3d.png", "Rule 30 - 3D Scatter", 10000)
.expect("Failed to create 3D scatter plot");
println!("\nDone! Check the generated PNG files.");
println!("\nNote: This implementation uses bitwise operations on a u32, making it very fast!");
println!("Rule 30 exhibits chaotic behavior - Wolfram used it in Mathematica's PRNG.");
}

View File

@ -0,0 +1,32 @@
use crate::RandomGenerator;
// Linear Congruential Generator
pub struct Lcg {
state: u64,
a: u64, // multiplier
c: u64, // increment
m: u64, // modulus
}
impl Lcg {
pub fn new(seed: u64, a: u64, c: u64, m: u64) -> Self {
Lcg {
state: seed,
a,
c,
m,
}
}
}
// Implement the RandomGenerator trait for LCG
impl RandomGenerator for Lcg {
fn next(&mut self) -> u64 {
self.state = (self.a.wrapping_mul(self.state).wrapping_add(self.c)) % self.m;
self.state
}
fn modulus(&self) -> u64 {
self.m
}
}

View File

@ -0,0 +1,38 @@
use crate::RandomGenerator;
// Linear Feedback Shift Register
// This implementation only REALLY HAS SUPPORT FOR 32 BIT NUMBERS!!
//
pub struct Lfsr {
state: u32,
a: u32,
b: u32,
c: u32,
m: u32,
}
impl Lfsr {
pub fn new(seed: u32, a: u32, b: u32, c: u32, m: u32) -> Self {
Lfsr {
state: seed,
a,
b,
c,
m,
}
}
}
// Implement the RandomGenerator trait for LCG
impl RandomGenerator for Lfsr {
fn next(&mut self) -> u64 {
self.state = self.state ^ (self.state << self.a);
self.state = self.state ^ (self.state >> self.b);
self.state = self.state ^ (self.state << self.c);
self.state as u64
}
fn modulus(&self) -> u64 {
self.m as u64
}
}

View File

@ -0,0 +1,31 @@
// Module declarations
mod lcg;
mod lfsr;
mod pcg;
mod rule30;
// Re-export all PRNG types
pub use lcg::Lcg;
pub use lfsr::Lfsr;
pub use pcg::Pcg32;
pub use rule30::Rule30;
// Trait that all PRNGs will implement
pub trait RandomGenerator {
/// Generate the next random integer
fn next(&mut self) -> u64;
/// Return the modulus (range) of the generator
fn modulus(&self) -> u64;
// Default implementations that all PRNGs get for free!
/// Generate a uniform random number in [0, 1)
fn next_uniform(&mut self) -> f64 {
self.next() as f64 / self.modulus() as f64
}
/// Generate n samples as a vector
fn generate_samples(&mut self, n: u64) -> Vec<f64> {
(0..n).map(|_| self.next_uniform()).collect()
}
}

View File

@ -0,0 +1,94 @@
use crate::RandomGenerator;
// DAS COMMENT:
// The prompt for creating this code was verbatim: Okay, now problem 3 is an interesting pro AI
// take. The prompt for problem 3 is "Write code to implement PCG32 in my favorite programming
// language (Rust!)" Please do similar statistics and procedures as LFSR and LCG.
//
// For your context, previous RNGs have had a little help for me to understand how traits work in
// Rust, but the implementations are almost entirely mine. This was generated using a Claude Code
// session with Sonnet 4.5.
// PCG32 - Permuted Congruential Generator
// A modern, high-quality PRNG with excellent statistical properties
// Uses a 64-bit LCG internally with output permutation
pub struct Pcg32 {
state: u64, // Internal LCG state (64-bit)
increment: u64, // Must be odd
}
impl Pcg32 {
// Standard PCG32 parameters
const MULTIPLIER: u64 = 6364136223846793005;
const DEFAULT_INCREMENT: u64 = 1442695040888963407;
pub fn new(seed: u64) -> Self {
// DAS - Any new instance of Pcg immediately runs through the new_with_increment function
Pcg32::new_with_increment(seed, Self::DEFAULT_INCREMENT)
}
pub fn new_with_increment(seed: u64, increment: u64) -> Self {
let mut pcg = Pcg32 {
state: 0,
increment: (increment << 1) | 1, // Ensure increment is odd
// DAS - I did NOT tell claude to do this. It basically copied the prose entirely on
// it's own, and Rust's syntax is almost exactly the same as written. This shifts the
// whole increment one bit left, and ensures the 2.pow(0) bit is always true (aka, 1,
// and always odd).
};
// Initialize state properly
//
// DAS - This is that first LCG step. Claude here I think is
// technically skipping step 3. It's just adding the value to the seed, and then stepping
// (steps 4 and 5 only). For the purpose of AI authorship, I'm going to let it rock and
// we'll see what happens.
pcg.state = pcg.state.wrapping_add(seed);
pcg.step();
pcg
}
// Internal LCG step
fn step(&mut self) {
// DAS - This is a basic LCG implementation.
self.state = self
.state
.wrapping_mul(Self::MULTIPLIER)
.wrapping_add(self.increment);
}
// PCG output permutation: XSH-RR (xorshift high, random rotation)
fn output(state: u64) -> u32 {
// XOR high and low parts
let xorshifted = (((state >> 18) ^ state) >> 27) as u32;
let rot = (state >> 59) as u32;
// Random rotation
//
// DAS - DGC, I think your implementation of this is wrong in the homework. You say "Return
// (xorshifted >> rot)", but wouldn't that pad zeros and not truly 'rotate' the number? At
// least, that's what Claude is intuiting here by using rotate_right() instead.
xorshifted.rotate_right(rot)
}
}
impl RandomGenerator for Pcg32 {
//DAS - This is implemenating the trait for this specific module. Man, I love Rust.
fn next(&mut self) -> u64 {
let old_state = self.state;
self.step();
//DAS - Techincally we've been fudging things as u32. We need to go back to u64 for all our
//nice traits to work with the plotting functions and statistics in the main script.
Self::output(old_state) as u64
//DAS - This does exactly as first described in the HW. Save the old state, advance the
//state, permute on the old state and output the permuted old state.
}
fn modulus(&self) -> u64 {
u32::MAX as u64
}
}

View File

@ -0,0 +1,58 @@
use crate::RandomGenerator;
// Rule 30 Cellular Automaton
// Elementary cellular automaton discovered by Stephen Wolfram
// Uses 32 cells with periodic boundary conditions
// Each generation, the entire 32-cell state is read as a 32-bit number
pub struct Rule30 {
state: u32, // 32 cells packed into a single u32
}
impl Rule30 {
pub fn new(seed: u32) -> Self {
// Initialize with the seed as the initial state
// If seed is 0, use a single 1 bit in the center (bit 16)
let initial_state = if seed == 0 { 1 << 16 } else { seed };
Rule30 {
state: initial_state,
}
}
// Apply Rule 30 for one generation with periodic boundary conditions
// This operates on all 32 cells simultaneously using bitwise operations
fn step(&mut self) {
// For Rule 30: new_cell = left XOR (center OR right)
// With periodic boundaries:
// - left neighbor of bit 0 is bit 31
// - right neighbor of bit 31 is bit 0
let left = self.state.rotate_right(1); // Shift right with wrap
let center = self.state;
let right = self.state.rotate_left(1); // Shift left with wrap
// Rule 30: output = left XOR (center OR right)
self.state = left ^ (center | right);
}
// Convert state to uniform [0, 1) using the formula from homework:
// u = sum(s_b * 2^(-b)) for b = 1 to 32
fn state_to_uniform(&self) -> f64 {
// This is equivalent to state / 2^32
self.state as f64 / (u32::MAX as f64 + 1.0)
}
}
impl RandomGenerator for Rule30 {
fn next(&mut self) -> u64 {
// Advance one generation
self.step();
// Return the entire 32-bit state as the random number
self.state as u64
}
fn modulus(&self) -> u64 {
// The state ranges from 0 to 2^32 - 1
(u32::MAX as u64) + 1
}
}

View File

@ -0,0 +1 @@
{"rustc_fingerprint":4812792677330984170,"outputs":{"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/opt/homebrew/Cellar/rust/1.92.0\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.92.0 (ded5c06cf 2025-12-08) (Homebrew)\nbinary: rustc\ncommit-hash: ded5c06cf21d2b93bffd5d884aa6e96934ee4234\ncommit-date: 2025-12-08\nhost: aarch64-apple-darwin\nrelease: 1.92.0\nLLVM version: 21.1.7\n","stderr":""}},"successes":{}}

View File

@ -0,0 +1,3 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by cargo.
# For information about cache directory tags see https://bford.info/cachedir/

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[]","declared_features":"[\"core\", \"default\", \"rustc-dep-of-std\", \"std\"]","target":6569825234462323107,"profile":5347358027863023418,"path":16242591911184827477,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/adler2-9f452af1aede1798/dep-lib-adler2","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[]","declared_features":"[\"core\", \"default\", \"rustc-dep-of-std\", \"std\"]","target":6569825234462323107,"profile":8276155916380437441,"path":16242591911184827477,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/adler2-c8e8b6eceba1aa8d/dep-lib-adler2","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"num-complex\", \"std\"]","target":6083125026265558093,"profile":8276155916380437441,"path":3817805816446374573,"deps":[[5157631553186200874,"num_traits",false,1702540368360024365]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/approx-8a05fbb9d7fefcd7/dep-lib-approx","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"num-complex\", \"std\"]","target":6083125026265558093,"profile":5347358027863023418,"path":3817805816446374573,"deps":[[5157631553186200874,"num_traits",false,12150174319006015928]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/approx-8ee5a9328039d6a0/dep-lib-approx","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[]","declared_features":"[]","target":6962977057026645649,"profile":3033921117576893,"path":4405214941553509729,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/autocfg-c7e245154ebc45d3/dep-lib-autocfg","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[]","declared_features":"[\"arbitrary\", \"bytemuck\", \"example_generated\", \"serde\", \"serde_core\", \"std\"]","target":7691312148208718491,"profile":8276155916380437441,"path":16528468883283760793,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bitflags-a15d76f739408839/dep-lib-bitflags","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[]","declared_features":"[\"arbitrary\", \"bytemuck\", \"example_generated\", \"serde\", \"serde_core\", \"std\"]","target":7691312148208718491,"profile":5347358027863023418,"path":16528468883283760793,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bitflags-b2bb7325319f27d9/dep-lib-bitflags","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[\"default\"]","declared_features":"[\"compiler_builtins\", \"core\", \"default\", \"example_generated\", \"rustc-dep-of-std\"]","target":12919857562465245259,"profile":5347358027863023418,"path":2174272235224428519,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bitflags-c4e0592364dd61d6/dep-lib-bitflags","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[\"default\"]","declared_features":"[\"compiler_builtins\", \"core\", \"default\", \"example_generated\", \"rustc-dep-of-std\"]","target":12919857562465245259,"profile":8276155916380437441,"path":2174272235224428519,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bitflags-df0c416b27f7f83c/dep-lib-bitflags","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[\"extern_crate_alloc\"]","declared_features":"[\"aarch64_simd\", \"align_offset\", \"alloc_uninit\", \"avx512_simd\", \"bytemuck_derive\", \"const_zeroed\", \"derive\", \"extern_crate_alloc\", \"extern_crate_std\", \"impl_core_error\", \"latest_stable_rust\", \"min_const_generics\", \"must_cast\", \"must_cast_extra\", \"nightly_docs\", \"nightly_float\", \"nightly_portable_simd\", \"nightly_stdsimd\", \"pod_saturating\", \"track_caller\", \"transparentwrapper_extra\", \"unsound_ptr_pod_impl\", \"wasm_simd\", \"zeroable_atomics\", \"zeroable_maybe_uninit\", \"zeroable_unwind_fn\"]","target":5195934831136530909,"profile":9981887903420318623,"path":15419217928792296880,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bytemuck-36a006046e371706/dep-lib-bytemuck","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[\"extern_crate_alloc\"]","declared_features":"[\"aarch64_simd\", \"align_offset\", \"alloc_uninit\", \"avx512_simd\", \"bytemuck_derive\", \"const_zeroed\", \"derive\", \"extern_crate_alloc\", \"extern_crate_std\", \"impl_core_error\", \"latest_stable_rust\", \"min_const_generics\", \"must_cast\", \"must_cast_extra\", \"nightly_docs\", \"nightly_float\", \"nightly_portable_simd\", \"nightly_stdsimd\", \"pod_saturating\", \"track_caller\", \"transparentwrapper_extra\", \"unsound_ptr_pod_impl\", \"wasm_simd\", \"zeroable_atomics\", \"zeroable_maybe_uninit\", \"zeroable_unwind_fn\"]","target":5195934831136530909,"profile":14653592838583397795,"path":15419217928792296880,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/bytemuck-ee25914e41fe7a7d/dep-lib-bytemuck","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"i128\", \"std\"]","target":8344828840634961491,"profile":5347358027863023418,"path":14543804270015332012,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/byteorder-dfce37e4b4f1b6c5/dep-lib-byteorder","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[\"default\", \"std\"]","declared_features":"[\"default\", \"i128\", \"std\"]","target":8344828840634961491,"profile":8276155916380437441,"path":14543804270015332012,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/byteorder-fc7394eaa24c66af/dep-lib-byteorder","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[]","declared_features":"[\"core\", \"rustc-dep-of-std\"]","target":13840298032947503755,"profile":8276155916380437441,"path":365716426712614768,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/cfg-if-251dd31bc984370b/dep-lib-cfg_if","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@ -0,0 +1 @@
{"rustc":12211934750107851607,"features":"[]","declared_features":"[\"core\", \"rustc-dep-of-std\"]","target":13840298032947503755,"profile":5347358027863023418,"path":365716426712614768,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/cfg-if-c0ee831ad1254d37/dep-lib-cfg_if","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View File

@ -0,0 +1 @@
This file has an mtime of when this was started.

Some files were not shown because too many files have changed in this diff Show More