<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="/css/rss-browser.css" ?>
<rss version="2.0">
	<channel>
		<title>Perturb.org - Scott's Geek Stuff</title>
		<link>http://www.perturb.org/</link>
		<description>Just Geek Stuff</description>

		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1458/</guid>
			<title>Perl: A simple module that doubles as a script</title>
			<link>http://www.perturb.org/display/entry/1458/</link>
			<description>&lt;p&gt;I have a small Perl script that defines a handful of functions. Perl allows you to make a library that doubles as a script when called directly. Using &lt;code&gt;caller()&lt;/code&gt; you can determine if your script was loaded via a &lt;code&gt;require()&lt;/code&gt; call, or called directly. This allows you to export functions if called as a library, but run code if called directly via: &lt;code&gt;perl my_lib.pl&lt;/code&gt;.&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-perl&quot;&gt;# my_lib.pl
		if (!caller()) {
		    say greet(&quot;Scott&quot;);
		}
		
		sub greet {
		    my $name = shift();
		
		    return &quot;Hello $name&quot;;
		}
		
		1; # Required if you load as a library&lt;/code&gt;&lt;/pre&gt;
		&lt;p&gt;Use a &lt;code&gt;require()&lt;/code&gt; call to load the module and get access to the &lt;code&gt;greet()&lt;/code&gt; function.&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-perl&quot;&gt;# main.pl
		require(&quot;/path/my_lib.pl&quot;);
		
		say greet(&quot;Foo&quot;);&lt;/code&gt;&lt;/pre&gt;</description>
			<pubDate>Sat, 01 Aug 2026 12:02:05 -0700</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1457/</guid>
			<title>Summary of each book in the Odyssey</title>
			<link>http://www.perturb.org/display/entry/1457/</link>
			<description>&lt;h3&gt;The Odyssey by Homer&lt;/h3&gt;
		&lt;ol&gt;
		&lt;li&gt;Odysseus&#039;s house is full of suitors eating all his food and drinking his wine waiting for Athena to choose a new husband&lt;/li&gt;
		&lt;li&gt;Telemachus calls a council of suitors to try and get rid of them, but the mock him and decide to stay&lt;/li&gt;
		&lt;li&gt;Telemachus sails to Pylos to meet King Nestor and ask about his father&#039;s Whereabouts&lt;/li&gt;
		&lt;li&gt;Telemachus reaches Sparta and learns his father is trapped on Calypso&#039;s island. The suitors plan ambush and kill Telemachus when he returns&lt;/li&gt;
		&lt;li&gt;Odysseus builds a raft and sails for 17 days besieged by Poseidon&#039;s wrath. The raft is destroyed and he swims to shore.&lt;/li&gt;
		&lt;li&gt;Nausicaa finds Odysseus and takes him to her father&#039;s house for a weird washing party. She directs him to her royal parents.&lt;/li&gt;
		&lt;li&gt;The king senses Odysseus greatness and offers his daughter in marriage but Odysseus declines and only wants to return home.&lt;/li&gt;
		&lt;li&gt;The Phaeacian compete in sports style games and recruit Odysseus. He says he is too old and worn out from the war.&lt;/li&gt;
		&lt;li&gt;Odysseus gets captured by a huge cyclops and kept in a cave. Odysseus blinds the Cyclops with a flame stick and escapes to his boat taunting the cyclops as he leaves.&lt;/li&gt;
		&lt;li&gt;Circe turns Odysseus&#039;s men into pigs and tempts Odysseus into her bed. He makes her swear an oath she won&#039;t harm him on his quest. She tells them they must go to the underworld next.&lt;/li&gt;
		&lt;li&gt;Odysseus travels to the underworld and meets on his dead crewmen who fell off Circe&#039;s roof and broke his neck. He also meets a ghost who looks like his mother and it causes him grief.&lt;/li&gt;
		&lt;li&gt;Odysseus is warned about the Siren&#039;s call. He tells his men to bind him to the mast and ignore his pleas for freedom. The men put wax in their ears and row past the Sirens. His men, starving, slaughter a sacred cow so Zeus destroys their ship and drowns everyone except Odysseus.&lt;/li&gt;
		&lt;li&gt;Odysseus makes it back to Ithaca, but he doesn&#039;t recognize the location. Athena transforms him into a shepherd and tells him to go see the man in charge of his pigs.&lt;/li&gt;
		&lt;li&gt;Odysseus meets the swineherd who welcomes him warmly without recognizing him. They share a meal and stories of his travels.&lt;/li&gt;
		&lt;li&gt;Telemachus heads back to Ithaca after Athena warns him of the suitors ambush. Odysseus reveals his identity to the swineherd and they head to Oddysseus&#039;s home.&lt;/li&gt;
		&lt;li&gt;Telemachus arrives at the swineherds home and meets his father who is still disguised. The reunite and plot to murder the suitors.&lt;/li&gt;
		&lt;li&gt;The three travel to Odysseus&#039;s home and the goatherd mocks and kicks him. Odysseus ignores him and meets his dog who recognizes him even in disguise. The suitors assault and insult the disguised Odysseus.&lt;/li&gt;
		&lt;li&gt;A beggar arrives at the house and challenges Odysseus, but Odysseus knocks his down pretty easily. Eurymachus throws a stool at Odysseus, while he observes the suitors behavior.&lt;/li&gt;
		&lt;li&gt;Odysseus and Telemachus remove the weapons from the hall. Nurse Eurycleia recognizes the disguised Odysseus by a scar on his foot, but he swears her to secrecy.&lt;/li&gt;
		&lt;li&gt;Theoclymenus foresees doom for the suitors, prophesying their impending death, but they mock him and dismiss his warning.&lt;/li&gt;
		&lt;li&gt;Penelope brings out Odysseus&#039;s great bow and announces a contest to win her hand. The suitors all fail to string the bow, Odysseus steps up, strings the bow and shoots the arrow through twelve axes heads and wins the contest.&lt;/li&gt;
		&lt;/ol&gt;</description>
			<pubDate>Wed, 15 Jul 2026 07:57:37 -0700</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1456/</guid>
			<title>Git: Keep two branches in sync</title>
			<link>http://www.perturb.org/display/entry/1456/</link>
			<description>&lt;p&gt;I have a Git repository with a primary branch that I maintain actively. I also have a separate feature branch that I&#039;d like to keep in sync with the main branch, and alert if there are any conflicts &lt;em&gt;immediately&lt;/em&gt;. Using Git hooks you can script automatically pulling each new commit from the primary branch to the feature branch.&lt;/p&gt;
		&lt;p&gt;Create a &lt;code&gt;.git/hooks/post-commit&lt;/code&gt; file and put these contents in it:&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;#!/bin/sh
		
		SRC=&quot;main&quot;
		DST=&quot;feature&quot;
		
		branch=$(git branch --show-current)
		
		if [ &quot;$branch&quot; = &quot;$SRC&quot; ]; then
		    commit=$(git rev-parse HEAD)
		
		    git checkout $DST &amp;amp;&amp;amp;
		    git cherry-pick &quot;$commit&quot; &amp;amp;&amp;amp;
		    git checkout main
		fi&lt;/code&gt;&lt;/pre&gt;
		&lt;p&gt;If there are conflicts, Git errors out immediately and leaves you on the feature branch to manually resolve the conflict.&lt;/p&gt;</description>
			<pubDate>Mon, 15 Jun 2026 09:24:42 -0700</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1455/</guid>
			<title>Using rsync to keep two directories in sync</title>
			<link>http://www.perturb.org/display/entry/1455/</link>
			<description>&lt;p&gt;I have two directories with (mostly) the same content that I want to keep in sync. Specifically I want to make sure that the newest version of each file is synced to the other directory. This allows me to update a file on either side, and that version will propagate to the other. You can do this with a bi-directional &lt;code&gt;rsync&lt;/code&gt; command:&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;rsync --update -av /dir/a/ /dir/b/
		rsync --update -av /dir/b/ /dir/a/&lt;/code&gt;&lt;/pre&gt;
		&lt;p&gt;Using &lt;code&gt;--update&lt;/code&gt; tells &lt;code&gt;rsync&lt;/code&gt; to skip files on the receiving side that are newer. If you sync &lt;code&gt;a&lt;/code&gt; -&amp;gt; &lt;code&gt;b&lt;/code&gt; and then &lt;code&gt;b&lt;/code&gt; -&amp;gt; &lt;code&gt;a&lt;/code&gt; you end up with both locations having the newest copy of each file.&lt;/p&gt;</description>
			<pubDate>Wed, 20 May 2026 11:40:26 -0700</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1454/</guid>
			<title>Perl: ULID generation</title>
			<link>http://www.perturb.org/display/entry/1454/</link>
			<description>&lt;p&gt;&lt;a href=&quot;https://github.com/ulid/spec&quot;&gt;ULID&#039;s&lt;/a&gt; are an interesting way to generate globally unique identifiers. Here is a quickie Perl implementation to generate ULIDs. This implementation does &lt;strong&gt;not&lt;/strong&gt; include the intra-millisecond monotonic increment however. If that feature is important to you consider checking out a more full-featured implementation like &lt;a href=&quot;https://github.com/scottchiefbaker/perl-ULID-Tiny&quot;&gt;ULID::Tiny&lt;/a&gt;.&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-perl&quot;&gt;for (1 .. 5) {
		    say(ulid());
		}&lt;/code&gt;&lt;/pre&gt;
		&lt;pre&gt;&lt;code class=&quot;language-perl&quot;&gt;sub ulid {
		    my $ts    = $_[0] || time() * 1000;
		    my $bytes = substr(pack(&quot;Q&amp;gt;&quot;, $ts), 2, 6);
		
		    # Append 10 random bytes
		    for (0 .. 9) { $bytes .= chr(int(rand(256))); }
		
		    # base32 encoding
		    my $bits  = unpack(&quot;B*&quot;, $bytes);
		    my $pad   = (5 - (length($bits) % 5)) % 5;
		    $bits    .= &#039;0&#039; x $pad;
		
		    # Chars to use for base32
		    my @CROCKFORD_CHARS = split(//, &#039;0123456789ABCDEFGHJKMNPQRSTVWXYZ&#039;);
		
		    my $result  = &#039;&#039;;
		    for (my $i = 0; $i &amp;lt; length($bits); $i += 5) {
		        my $chunk = substr($bits, $i, 5);
		        my $index = 0;
		        for my $bit (split //, $chunk) {
		            $index = ($index &amp;lt;&amp;lt; 1) | $bit;
		        }
		
		        $result .= $CROCKFORD_CHARS[$index];
		    }
		
		    return $result;
		}&lt;/code&gt;&lt;/pre&gt;
		&lt;p&gt;&lt;strong&gt;See also:&lt;/strong&gt; &lt;a href=&quot;https://www.perturb.org/display/1398_Perl_UUIDv7.html&quot;&gt;UUIDv7&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Sun, 26 Apr 2026 18:58:48 -0700</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1453/</guid>
			<title>Perl: Using Inline::C to embed C functions in your Perl scripts</title>
			<link>http://www.perturb.org/display/entry/1453/</link>
			<description>&lt;p&gt;Perl allows &quot;inline&quot; code written in other languages. This is useful because you can have native C functions interact with your Perl code. By placing your C code in the &lt;code&gt;__DATA__&lt;/code&gt; section of your Perl script you get clean separation between the two languages.&lt;/p&gt;
		&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;Inline::C&lt;/code&gt; does not understand &lt;code&gt;uint64_t&lt;/code&gt; in function definitions, so anything that interacts with Perl needs to use &lt;code&gt;UV&lt;/code&gt; instead. Internally C functions can use and interact with &lt;code&gt;uint64_t&lt;/code&gt; variables just fine.&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-perl&quot;&gt;use strict;
		use warnings;
		use v5.16;
		use Inline &#039;C&#039;;
		
		##############################################
		
		seed_splitmix64(time());
		
		for (1 .. 5) {
		    say splitmix64();
		}
		
		##############################################
		
		__DATA__
		__C__
		
		uint64_t x = 123456789;
		
		void seed_splitmix64(UV seed) {
		    x = seed;
		}
		
		UV splitmix64() {
		    uint64_t z = (x += 0x9e3779b97f4a7c15);
		    z = (z ^ (z &amp;gt;&amp;gt; 30)) * 0xbf58476d1ce4e5b9;
		    z = (z ^ (z &amp;gt;&amp;gt; 27)) * 0x94d049bb133111eb;
		
		    return z ^ (z &amp;gt;&amp;gt; 31);
		}&lt;/code&gt;&lt;/pre&gt;
		&lt;p&gt;This will compile the C code into a shared object in the &lt;code&gt;_Inline&lt;/code&gt; directory in whichever directory you instantiated your Perl script. Code is only compiled once (and where there are changes), so your script performance will be very high.&lt;/p&gt;</description>
			<pubDate>Thu, 23 Apr 2026 14:34:43 -0700</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1452/</guid>
			<title>Comparison of markup languages</title>
			<link>http://www.perturb.org/display/entry/1452/</link>
			<description>&lt;p&gt;I&#039;ve been investigating &lt;a href=&quot;https://www.json.org/&quot;&gt;JSON&lt;/a&gt; vs &lt;a href=&quot;https://yaml.org/&quot;&gt;YAML&lt;/a&gt; vs &lt;a href=&quot;https://toml.io/&quot;&gt;TOML&lt;/a&gt; for various applications. After testing many variations I ended up writing a &lt;a href=&quot;https://www.perturb.org/code/serialize_test.php&quot;&gt;simple tool&lt;/a&gt; to compare all three live.&lt;/p&gt;</description>
			<pubDate>Thu, 09 Apr 2026 10:58:41 -0700</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1451/</guid>
			<title>Linux: SFTP and SCP friendly login banners</title>
			<link>http://www.perturb.org/display/entry/1451/</link>
			<description>&lt;p&gt;To display a message when a user logs into your server, add the following to &lt;code&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# If it&#039;s an interactive terminal show the banner
		if [[ $- == *i* ]]; then
		    echo &quot;Welcome to the monitoring server&quot;
		    echo &quot;Configuration is stored in /etc/myapp&quot;
		fi&lt;/code&gt;&lt;/pre&gt;
		&lt;p&gt;This runs &lt;em&gt;only&lt;/em&gt; for interactive sessions. Non-interactive connections such as SFTP and SCP remain unaffected, which prevents automated processes from breaking.&lt;/p&gt;
		&lt;p&gt;&lt;strong&gt;See also:&lt;/strong&gt; The &lt;a href=&quot;https://github.com/scottchiefbaker/text_color&quot;&gt;text_color&lt;/a&gt; project.&lt;/p&gt;</description>
			<pubDate>Thu, 26 Mar 2026 14:07:00 -0700</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1450/</guid>
			<title>YAML is growing on me</title>
			<link>http://www.perturb.org/display/entry/1450/</link>
			<description>&lt;p&gt;The more I learn about YAML, the more I like it. JSON is great as a machine readable format, but it sucks at being human readable. Want to add an element, better make sure you have &lt;strong&gt;all&lt;/strong&gt; the commas and curly braces in the &lt;strong&gt;exact&lt;/strong&gt; right place or the whole thing will be unusable. YAML on the other hand is designed to be human readable and modifiable. It&#039;s a very simple key/value system using indentation to represent layers. &lt;/p&gt;
		&lt;p&gt;PHP has a &lt;a href=&quot;https://bd808.com/pecl-file_formats-yaml/&quot;&gt;PECL module&lt;/a&gt; with good YAML support. There are also pure PHP versions if you&#039;re unable to install PECL modules. &lt;a href=&quot;https://github.com/symfony/yaml&quot;&gt;Symfony&lt;/a&gt; provides one, and so does &lt;a href=&quot;https://github.com/mustangostang/spyc&quot;&gt;Spyc&lt;/a&gt;. I prefer the latter because it&#039;s a single file and very easy to install.&lt;/p&gt;
		&lt;p&gt;On the Perl side there is &lt;a href=&quot;https://metacpan.org/pod/YAML::XS&quot;&gt;YAML::XS&lt;/a&gt;, &lt;a href=&quot;https://metacpan.org/pod/YAML::PP&quot;&gt;YAML::PP&lt;/a&gt;, and &lt;a href=&quot;https://metacpan.org/search?size=20&amp;amp;q=yaml&quot;&gt;many&lt;/a&gt; others. &lt;/p&gt;
		&lt;p&gt;Parsing YAML is very easy in just about every language I can find. If you have a complex data structure that you need humans to interact with use YAML please.&lt;/p&gt;
		&lt;p&gt;Here is a &lt;a href=&quot;https://jsonlint.com/json-vs-yaml&quot;&gt;great breakdown&lt;/a&gt; of when to use YAML vs JSON:&lt;/p&gt;
		&lt;table&gt;
		&lt;thead&gt;
		&lt;tr&gt;
		&lt;th&gt;Use Case&lt;/th&gt;
		&lt;th&gt;Recommended&lt;/th&gt;
		&lt;th&gt;Why&lt;/th&gt;
		&lt;/tr&gt;
		&lt;/thead&gt;
		&lt;tbody&gt;
		&lt;tr&gt;
		&lt;td&gt;API request/response&lt;/td&gt;
		&lt;td&gt;JSON&lt;/td&gt;
		&lt;td&gt;Universal support, strict parsing&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
		&lt;td&gt;Configuration files&lt;/td&gt;
		&lt;td&gt;YAML&lt;/td&gt;
		&lt;td&gt;Comments, readability&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
		&lt;td&gt;Browser/JavaScript&lt;/td&gt;
		&lt;td&gt;JSON&lt;/td&gt;
		&lt;td&gt;Native parsing&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
		&lt;td&gt;Kubernetes/Docker&lt;/td&gt;
		&lt;td&gt;YAML&lt;/td&gt;
		&lt;td&gt;Industry standard&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
		&lt;td&gt;Data interchange&lt;/td&gt;
		&lt;td&gt;JSON&lt;/td&gt;
		&lt;td&gt;Unambiguous, fast&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
		&lt;td&gt;Human-edited files&lt;/td&gt;
		&lt;td&gt;YAML&lt;/td&gt;
		&lt;td&gt;Less punctuation&lt;/td&gt;
		&lt;/tr&gt;
		&lt;/tbody&gt;
		&lt;/table&gt;
		&lt;p&gt;&lt;a href=&quot;https://perlpunk.github.io/yaml-test-schema/schemas.html&quot;&gt;YAML spec&lt;/a&gt; differences.&lt;/p&gt;</description>
			<pubDate>Wed, 25 Mar 2026 10:04:29 -0700</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1449/</guid>
			<title>C: Fill an array of unsigned integers with random data using getentropy()</title>
			<link>http://www.perturb.org/display/entry/1449/</link>
			<description>&lt;p&gt;Often I need to generate random unsigned integers for seeding PRNGs. The best way is using the &lt;code&gt;getentropy()&lt;/code&gt; system function to read OS level randomness into your array.&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;#include &amp;lt;sys/random.h&amp;gt;
		
		// Read from system random to fill up data structure
		int8_t fill_urandom(void *buf, size_t bytes) {
		    int8_t ok = getentropy(buf, bytes);
		
		    return (ok == 0);
		}&lt;/code&gt;&lt;/pre&gt;
		&lt;p&gt;Declare your array of integers, and then pass it as a pointer to this function to fill with random bytes from your OS. This will get you a bunch of random integers you can use for seeding PRNGs.&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;uint64_t seed[4];
		fill_urandom(seed, sizeof(seed));&lt;/code&gt;&lt;/pre&gt;</description>
			<pubDate>Sun, 11 Jan 2026 12:32:42 -0800</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1448/</guid>
			<title>Books of 2026</title>
			<link>http://www.perturb.org/display/entry/1448/</link>
			<description>&lt;p&gt;List of books I read in 2026. Also see the list of &lt;a href=&quot;/display/1412_Books_of_2025.html&quot;&gt;2025&lt;/a&gt;. The date indicated denotes the date I started reading the book.&lt;/p&gt;
		&lt;p&gt;2026-01-01 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9781453080054&quot;&gt;White Fang&lt;/a&gt; by Jack London - 180 pages&lt;br /&gt;
		2026-01-03 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9781409146322&quot;&gt;Hollow Man&lt;/a&gt; by John Dickson Carr - 213 pages&lt;br /&gt;
		2026-01-06 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780765382030&quot;&gt;The Three-body Problem&lt;/a&gt; by Cixin Liu - 400 pages&lt;br /&gt;
		2026-01-12 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780345477576&quot;&gt;Star Wars: Revelation&lt;/a&gt; by Karen Traviss - 410 pages&lt;br /&gt;
		2026-01-19 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780345376596&quot;&gt;Pale Blue Dot&lt;/a&gt; by Carl Sagan - 342 pages&lt;br /&gt;
		2026-01-25 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780593820254&quot;&gt;Dungeon Crawler Carl&lt;/a&gt; by Matt Dinniman - 450 pages&lt;br /&gt;
		2026-02-01 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780593135228&quot;&gt;Project Hail Mary&lt;/a&gt; by Andy Weir - 478 pages&lt;br /&gt;
		2026-02-09 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780765386694&quot;&gt;The Dark Forest&lt;/a&gt; by Cixin Liu - 512 pages&lt;br /&gt;
		2026-02-18 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780399563874&quot;&gt;The Hike&lt;/a&gt; by Drew Magary - 278 pages&lt;br /&gt;
		2026-02-22 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9781538541920&quot;&gt;Fletch&lt;/a&gt; by Gregory Mcdonald - 249 pages&lt;br /&gt;
		2026-02-26 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780060589462&quot;&gt;Zen And The Art Of Motorcycle Maintenance&lt;/a&gt; by Robert M. Pirsig - 540 pages&lt;br /&gt;
		2026-03-06 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9781783299010&quot;&gt;Aliens: The Female War&lt;/a&gt; by Steve Perry - 258 pages&lt;br /&gt;
		2026-03-11 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780060548254&quot;&gt;The Crystal Cave&lt;/a&gt; by Mary Stewart - 522 pages&lt;br /&gt;
		2026-03-20 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780593734223&quot;&gt;Nexus&lt;/a&gt; by Yuval Noah Harari - 420 pages&lt;br /&gt;
		2026-03-26 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+0345428544&quot;&gt;Star Wars: Onslaught&lt;/a&gt; by Michael A. Stackpole - 292 pages&lt;br /&gt;
		2026-03-31 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780765386632&quot;&gt;Death&#039;s End&lt;/a&gt; by Cixin Liu - 590 pages&lt;br /&gt;
		2026-04-09 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780141321059&quot;&gt;The Call Of The Wild&lt;/a&gt; by Jack London - 160 pages&lt;br /&gt;
		2026-04-19 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780062074201&quot;&gt;Wayne Of Gotham&lt;/a&gt; by Tracy Hickman - 296 pages&lt;br /&gt;
		2026-04-23 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780765332035&quot;&gt;Unwept&lt;/a&gt; by Tracy Hickman - 268 pages&lt;br /&gt;
		2026-04-27 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+0345428560&quot;&gt;Star Wars: Ruin&lt;/a&gt; by Michael A. Stackpole - 292 pages&lt;br /&gt;
		2026-05-10 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780316405348&quot;&gt;Invisible&lt;/a&gt; by James Patterson - 401 pages&lt;br /&gt;
		2026-05-18 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780679728757&quot;&gt;Blood Meridian&lt;/a&gt; by Cormac McCarthy - 349 pages&lt;br /&gt;
		2026-05-22 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780345477477&quot;&gt;Star Wars: Invincible&lt;/a&gt; by Troy Denning - 347 pages&lt;br /&gt;
		2026-05-28 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+0425177173&quot;&gt;Atlantis Found&lt;/a&gt; by Clive Cussler - 532 pages&lt;br /&gt;
		2026-06-06 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+0425133516&quot;&gt;The Hunt For Red October&lt;/a&gt; by Tom Clancy - 469 pages&lt;br /&gt;
		2026-06-24 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+0553298038&quot;&gt;Star Wars: Ambush at Corellia&lt;/a&gt; by Roger Macbride Allen - 308 pages&lt;br /&gt;
		2026-06-29 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780316419826&quot;&gt;Unsolved&lt;/a&gt; by James Patterson - 468 pages&lt;br /&gt;
		2026-07-13 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780451474339&quot;&gt;The Odyssey&lt;/a&gt; by Homer - 384 pages&lt;br /&gt;
		2026-07-18 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780425280188&quot;&gt;Piranha&lt;/a&gt; by Clive Cussler - 422 pages&lt;br /&gt;
		2026-08-08 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9781250750303&quot;&gt;The Empress Of Salt And Fortune&lt;/a&gt; by Nghi Vo - 111 pages&lt;br /&gt;
		2026-xx-xx - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780316458405&quot;&gt;A Violent Masterpiece&lt;/a&gt; by Jordan Harper - 372 pages  &lt;/p&gt;
		&lt;h3&gt;Inheritance Cycle&lt;/h3&gt;
		&lt;p&gt;2026-05-02 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780375826696&quot;&gt;Eragon&lt;/a&gt; by Christopher Paolini - 503 pages&lt;br /&gt;
		2026-06-13 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780375840401&quot;&gt;Eldest&lt;/a&gt; by Christopher Paolini - 679 pages&lt;br /&gt;
		2026-07-27 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780375826740&quot;&gt;Brisingr&lt;/a&gt; by Christopher Paolini - 763 pages&lt;br /&gt;
		2026-xx-xx - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780375846311&quot;&gt;Inheritance&lt;/a&gt; by Christopher Paolini - 849 pages  &lt;/p&gt;
		&lt;h3&gt;Dragonlance: Chronicles&lt;/h3&gt;
		&lt;p&gt;2026-04-11 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+9780786915743&quot;&gt;Dragons Of Autumn Twilight&lt;/a&gt; by Margaret Weis - 444 pages&lt;br /&gt;
		2022-07-07 - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;tbm=bks&amp;amp;q=isbn+9780786916092&quot;&gt;Dragons Of Winter Night&lt;/a&gt; by Margaret Weis - 395 pages&lt;br /&gt;
		2022-xx-xx - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;tbm=bks&amp;amp;q=isbn+9780786915897&quot;&gt;Dragons Of Spring Dawning&lt;/a&gt; by Margaret Weis - 379 pages&lt;br /&gt;
		2022-xx-xx - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;tbm=bks&amp;amp;q=isbn+9780786927081&quot;&gt;Dragons Of Summer Flame&lt;/a&gt; by Margaret Weis - 586 pages&lt;/p&gt;
		&lt;h3&gt;Dragonlance: War of Souls&lt;/h3&gt;
		&lt;p&gt;2026-xx-xx- &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+0786918071&quot;&gt;Dragons Of A Fallen Sun&lt;/a&gt; by Margaret Weis - 627 pages&lt;br /&gt;
		2026-xx-xx - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+0786927062&quot;&gt;Dragons Of A Lost Star&lt;/a&gt; by Margaret Weis - 550 pages&lt;br /&gt;
		2026-xx-xx - &lt;a href=&quot;//www.google.com/search?tbo=p&amp;amp;q=isbn+0786929502&quot;&gt;Dragons Of A Vanished Moon&lt;/a&gt; by Margaret Weis - 629 pages&lt;/p&gt;</description>
			<pubDate>Thu, 01 Jan 2026 10:50:29 -0800</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1447/</guid>
			<title>How far does Gandalf fall when fighting the Balrog in Khazad Dum?</title>
			<link>http://www.perturb.org/display/entry/1447/</link>
			<description>&lt;p&gt;In the extended edition of Fellowship of the Ring Gandalf fights the Balrog and then falls for about 70 seconds.&lt;/p&gt;
		&lt;p&gt;It takes about 12 seconds to reach terminal velocity: 0.5 * g * t^2 = 0.5 * 9.81 * 12^2 ~ 706m&lt;/p&gt;
		&lt;p&gt;The remaining 58 seconds Gandalf is at terminal velocity (not speeding up) of 53m/s which is v * t = 53 * 58 ~ 3074m. For a total of 3780 meters, or about 2.35 miles.&lt;/p&gt;
		&lt;p&gt;Pretty impressive free-fall considering they were ALREADY under ground.&lt;/p&gt;</description>
			<pubDate>Wed, 24 Dec 2025 21:16:09 -0800</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1446/</guid>
			<title>Perl: biski64 and sfc64 PRNG</title>
			<link>http://www.perturb.org/display/entry/1446/</link>
			<description>&lt;p&gt;&lt;a href=&quot;https://github.com/danielcota/biski64&quot;&gt;Biski64&lt;/a&gt; is a new PRNG there is extremely fast and also very simple. This one was pretty simple so I ported it to Perl in &lt;a href=&quot;https://www.perturb.org/code/syntax_highlight.php?file=biski64.pl&quot;&gt;biski64.pl&lt;/a&gt;.&lt;/p&gt;
		&lt;p&gt;SFC64 is also largely considered on of the better PRNGs so I ported it also in &lt;a href=&quot;https://www.perturb.org/code/syntax_highlight.php?file=sfc64.pl&quot;&gt;sfc64.pl&lt;/a&gt;.&lt;/p&gt;</description>
			<pubDate>Tue, 23 Dec 2025 10:08:47 -0800</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1445/</guid>
			<title>PRNG: PCG64 in Perl</title>
			<link>http://www.perturb.org/display/entry/1445/</link>
			<description>&lt;p&gt;I found a &lt;a href=&quot;https://github.com/alvoskov/SmokeRand/blob/main/generators/pcg64_64.c&quot;&gt;PCG64 implementation&lt;/a&gt; that I was able to borrow and convert to pure Perl:&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-perl&quot;&gt;# PCG64 RXS-M-XS &quot;simple&quot; variant
		#my $seeds = [12, 34];
		#my $rand  = pcg64_perl($seeds);
		sub pcg64_perl {
		    my $seeds = $_[0];
		    my $ret   = (($seeds-&amp;gt;[0] &amp;gt;&amp;gt; (($seeds-&amp;gt;[0] &amp;gt;&amp;gt; 59) + 5)) ^ $seeds-&amp;gt;[0]);
		
		    use integer;
		    $ret *= 12605985483714917081;
		    $seeds-&amp;gt;[0] = $seeds-&amp;gt;[0] * 6364136223846793005 + $seeds-&amp;gt;[1];
		    no integer;
		
		    $ret = ($ret &amp;gt;&amp;gt; 43) ^ $ret;
		
		    return $ret;
		}&lt;/code&gt;&lt;/pre&gt;
		&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Bonus points because it&#039;s &lt;a href=&quot;https://www.perturb.org/code/prng-bench.pl&quot;&gt;really fast&lt;/a&gt;:&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;*               Rate xosh256**  biski64     sfc64     PCG32 Splitmix64     PCG64
		xosh256**  1589825/s        --     -26%      -48%      -52%       -58%      -65%
		biski64    2145923/s       35%       --      -30%      -35%       -43%      -53%
		sfc64      3058104/s       92%      43%        --       -8%       -19%      -33%
		PCG32      3311258/s      108%      54%        8%        --       -13%      -28%
		Splitmix64 3787879/s      138%      77%       24%       14%         --      -17%
		PCG64      4587156/s      189%     114%       50%       39%        21%        --&lt;/code&gt;&lt;/pre&gt;</description>
			<pubDate>Fri, 12 Dec 2025 18:33:07 -0800</pubDate>
		</item>
		
		<item>
			<guid isPermaLink="true">http://www.perturb.org/display/entry/1444/</guid>
			<title>PHP: Serve large audio/video files outside of the webroot</title>
			<link>http://www.perturb.org/display/entry/1444/</link>
			<description>&lt;p&gt;I have some large audio files that I need to serve via HTTPs. They need to be protected by my PHP login system so they cannot live &lt;em&gt;inside&lt;/em&gt; of the webroot. Fortunately there is a nifty Apache module named &lt;a href=&quot;https://github.com/nmaier/mod_xsendfile&quot;&gt;X-sendfile&lt;/a&gt;, that lets you serve files outside of the webroot.&lt;/p&gt;
		&lt;p&gt;Credential checking is done in PHP, and then you set a special HTTP header that Apache watches for. When Apaches sees the &lt;code&gt;X-Sendfile&lt;/code&gt; header it serves the file directly. This gets you all the advantages of a full-blown HTTP server handling your files, but the convenience and simplicity of PHP for handling authentication.&lt;/p&gt;
		&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;if ($authorized) {
		    $mime_type = mime_from_filename($filepath);
		
		    header(&quot;Content-Type: $mime_type&quot;);
		    header(&quot;X-Sendfile: $filepath&quot;);
		    exit;
		}&lt;/code&gt;&lt;/pre&gt;
		&lt;p&gt;&lt;strong&gt;See also:&lt;/strong&gt; &lt;a href=&quot;https://www.perturb.org/display/1443_PHP_Get_the_mime_type_for_a_file.html&quot;&gt;Get mime type for file&lt;/a&gt;&lt;/p&gt;</description>
			<pubDate>Tue, 02 Dec 2025 11:57:04 -0800</pubDate>
		</item>
		
	</channel>
</rss>
