Sorry

This feed does not validate.

In addition, interoperability with the widest range of feed readers could be improved by implementing the following recommendation.

Source: http://www.perturb.org/atom.php

  1. <br />
  2. <b>Warning</b>:  Undefined variable $out in <b>/home/bakers/html/perturb.class.php</b> on line <b>1314</b><br />
  3. <br />
  4. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  5. <br />
  6. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  7. <br />
  8. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  9. <br />
  10. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  11. <br />
  12. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  13. <br />
  14. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  15. <br />
  16. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  17. <br />
  18. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  19. <br />
  20. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  21. <br />
  22. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  23. <br />
  24. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  25. <br />
  26. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  27. <br />
  28. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  29. <br />
  30. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  31. <br />
  32. <b>Warning</b>:  Undefined variable $summary in <b>/home/bakers/html/perturb.class.php</b> on line <b>1353</b><br />
  33. <?xml version="1.0" encoding="iso-8859-1"?>
  34. <?xml-stylesheet type="text/css" href="/css/atom-browser.css" ?>
  35. <feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en"> <title>Perturb.org - Scott's Geek Blog</title>
  36. <modified>2025-08-28T14:17:19-07:00</modified> <link rel="alternate" type="text/html" href="http://www.perturb.org" /> <tagline>Geek blog</tagline>
  37. <id>tag:www.perturb.org,2025://08</id>
  38. <generator>Perturb ATOM v0.1</generator>
  39. <entry xmlns="http://purl.org/atom/ns#">
  40. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1433/" />
  41. <title mode="escaped">Perl: Search and replace a string across your entire code base</title>
  42. <modified>2025-08-20T08:15:57-07:00</modified>
  43. <issued>2025-08-20T08:15:57-07:00</issued>
  44. <created>2025-08-20T08:15:57-07:00</created>
  45. <id>http://www.perturb.org/display/entry/1433/</id>
  46. <summary type="text/plain"></summary>
  47. <author>
  48. <name>Scott Baker</name>
  49. <url>http://www.perturb.org/</url>
  50. <email>scott@perturb.org</email>
  51. </author>
  52. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  53. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  54.  
  55. I wanted to rename a function anywhere it was found in my code base. This requires going through every file and directory recursively, and checking each file. Using the Linux `find` command we can find *all* the files and then hand the search and replace off to Perl. Easy peasy. <br />
  56. <br />
  57. ```bash <br />
  58. find codebase/ -type f -exec perl -pi -E 's/foo/bar/g' {} + <br />
  59. ``` <br />
  60. <br />
  61. or using `fd` instead: <br />
  62. <br />
  63. ```bash <br />
  64. fd . codebase/ --type f --exec-batch -pi -E 's/foo/bar/g' {} <br />
  65. ```
  66. ]]>
  67. </content>
  68. </entry>
  69. <entry xmlns="http://purl.org/atom/ns#">
  70. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1432/" />
  71. <title mode="escaped">Linux: Testing for x86_64-v3</title>
  72. <modified>2025-07-29T16:29:18-07:00</modified>
  73. <issued>2025-07-29T16:29:18-07:00</issued>
  74. <created>2025-07-29T16:29:18-07:00</created>
  75. <id>http://www.perturb.org/display/entry/1432/</id>
  76. <summary type="text/plain"></summary>
  77. <author>
  78. <name>Scott Baker</name>
  79. <url>http://www.perturb.org/</url>
  80. <email>scott@perturb.org</email>
  81. </author>
  82. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  83. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  84.  
  85. Modern Linux distributions are starting to require [x86_64-v3](https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels) capable CPUs to run. If you do not have a CPU modern enough you may not be able to install certain versions of Linux. To test if your hardware is capable you can run the following command: <br />
  86. <br />
  87. ``` <br />
  88. /usr/lib64/ld-linux-x86-64.so.2 --help <br />
  89. ``` <br />
  90. <br />
  91. Basically any CPU made after 2015 will be fine.
  92. ]]>
  93. </content>
  94. </entry>
  95. <entry xmlns="http://purl.org/atom/ns#">
  96. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1431/" />
  97. <title mode="escaped">PHP: Only start a session when it&#039;s needed</title>
  98. <modified>2025-06-21T11:29:02-07:00</modified>
  99. <issued>2025-06-21T11:29:02-07:00</issued>
  100. <created>2025-06-21T11:29:02-07:00</created>
  101. <id>http://www.perturb.org/display/entry/1431/</id>
  102. <summary type="text/plain"></summary>
  103. <author>
  104. <name>Scott Baker</name>
  105. <url>http://www.perturb.org/</url>
  106. <email>scott@perturb.org</email>
  107. </author>
  108. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  109. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  110.  
  111. I use sessions on my sites for user authentication. Calling `session_start()` initiates a session and allows me to check if the user is logged in or not. However, calling `session_start()` creates a new session for **every** hit on your site: bots, unauthenticated users, etc. This can lead to an _excess_ of session files on your filesystem. <br />
  112. <br />
  113. A better way is to explicitly call `start_session()` when your user logs in. On your other pages you can check if the user has the appropriate session cookie and start a session **only** when it's needed. <br />
  114. <br />
  115. ```PHP <br />
  116. function start_session_if_exists() { <br />
  117.    if (isset($_COOKIE[session_name()]) && session_status() !== PHP_SESSION_ACTIVE) { <br />
  118.        session_start(); <br />
  119.    } <br />
  120. } <br />
  121. ``` <br />
  122. <br />
  123. This will avoid creating a session for every hit on your site.
  124. ]]>
  125. </content>
  126. </entry>
  127. <entry xmlns="http://purl.org/atom/ns#">
  128. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1430/" />
  129. <title mode="escaped">CSS: Selecting text made easy</title>
  130. <modified>2025-06-17T09:58:19-07:00</modified>
  131. <issued>2025-06-17T09:58:19-07:00</issued>
  132. <created>2025-06-17T09:58:19-07:00</created>
  133. <id>http://www.perturb.org/display/entry/1430/</id>
  134. <summary type="text/plain"></summary>
  135. <author>
  136. <name>Scott Baker</name>
  137. <url>http://www.perturb.org/</url>
  138. <email>scott@perturb.org</email>
  139. </author>
  140. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  141. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  142.  
  143. You can apply the [user-select](https://developer.mozilla.org/en-US/docs/Web/CSS/user-select) CSS property to an element to control how it handles selecting text for copy and paste. This allows you to limit selecting text, or make it automatic. If you use the `all` property, anytime a user clicks on that element the text is automatically selected. This can be useful for keys or codes where the user is **expected** to copy and paste the text. <br />
  144. <br />
  145. ```css <br />
  146. .click_select { user-select: all; } <br />
  147. ``` <br />
  148. <br />
  149. Example: <br />
  150. <br />
  151. <style> <br />
  152. .click_select {  <br />
  153. user-select: all;  <br />
  154. } <br />
  155. .test_button { <br />
  156. border: 1px solid black;  <br />
  157. padding: 12px;  <br />
  158. border-radius: 4px;  <br />
  159. background: darkblue; <br />
  160. } <br />
  161. </style> <br />
  162. <br />
  163. <span class="click_select test_button">Click me!</span>
  164. ]]>
  165. </content>
  166. </entry>
  167. <entry xmlns="http://purl.org/atom/ns#">
  168. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1429/" />
  169. <title mode="escaped">Linux: Find all the text files in a directory</title>
  170. <modified>2025-06-06T18:30:02-07:00</modified>
  171. <issued>2025-06-06T18:30:02-07:00</issued>
  172. <created>2025-06-06T18:30:02-07:00</created>
  173. <id>http://www.perturb.org/display/entry/1429/</id>
  174. <summary type="text/plain"></summary>
  175. <author>
  176. <name>Scott Baker</name>
  177. <url>http://www.perturb.org/</url>
  178. <email>scott@perturb.org</email>
  179. </author>
  180. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  181. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  182.  
  183. I need to find all the _text_ files in a given directory for potential clean up. There is not a super easy way to find only text files, but I came up with a hacky solution: <br />
  184. <br />
  185. ```bash <br />
  186. # Using `fd` (new hotness) <br />
  187. fd . /tmp/ --exec file {} + | grep -P ":.*text" | cut -d: -f1 <br />
  188. <br />
  189. # Using old school `find` (old and busted) <br />
  190. find /tmp/ -exec file {} + | grep -P ":.*text" | cut -d: -f1 <br />
  191. ``` <br />
  192. <br />
  193. These rely on the `file` command to determine what the filetype is.
  194. ]]>
  195. </content>
  196. </entry>
  197. <entry xmlns="http://purl.org/atom/ns#">
  198. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1428/" />
  199. <title mode="escaped">Javascript: Copy string to clipboard</title>
  200. <modified>2025-06-03T15:25:29-07:00</modified>
  201. <issued>2025-06-03T15:25:29-07:00</issued>
  202. <created>2025-06-03T15:25:29-07:00</created>
  203. <id>http://www.perturb.org/display/entry/1428/</id>
  204. <summary type="text/plain"></summary>
  205. <author>
  206. <name>Scott Baker</name>
  207. <url>http://www.perturb.org/</url>
  208. <email>scott@perturb.org</email>
  209. </author>
  210. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  211. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  212.  
  213. I needed a modern way to copy a string to the clipboard in JavaScript. [Claude.ai](https://claude.ai) helped me come up with this: <br />
  214. <br />
  215. ```javascript <br />
  216. // With async/await <br />
  217. async function copyToClipboard(text) { <br />
  218. try { <br />
  219. await navigator.clipboard.writeText(text); <br />
  220. console.log('Copied to clipboard'); <br />
  221. } catch (err) { <br />
  222. console.error('Failed to copy: ', err); <br />
  223. } <br />
  224. } <br />
  225. ``` <br />
  226. <br />
  227. Then you simply call it with a string <br />
  228. <br />
  229. ```javascript <br />
  230. copyToClipboard("Hello world"); <br />
  231. ```
  232. ]]>
  233. </content>
  234. </entry>
  235. <entry xmlns="http://purl.org/atom/ns#">
  236. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1427/" />
  237. <title mode="escaped">Rocky 10 package versions</title>
  238. <modified>2025-06-02T15:10:07-07:00</modified>
  239. <issued>2025-06-02T15:10:07-07:00</issued>
  240. <created>2025-06-02T15:10:07-07:00</created>
  241. <id>http://www.perturb.org/display/entry/1427/</id>
  242. <summary type="text/plain"></summary>
  243. <author>
  244. <name>Scott Baker</name>
  245. <url>http://www.perturb.org/</url>
  246. <email>scott@perturb.org</email>
  247. </author>
  248. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  249. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  250.  
  251. RedHat Enterprise Linux/Rocky 10 has these versions of packages: <br />
  252. <br />
  253. | Package | Version  | <br />
  254. | ------- | -------- | <br />
  255. | Apache  | 2.4.63   | <br />
  256. | GCC     | 14.2.1   | <br />
  257. | Git     | 2.47.1   | <br />
  258. | Kernel  | 6.12     | <br />
  259. | MariaDB | 10.11.11 | <br />
  260. | OpenSSH | 9.9p1    | <br />
  261. | Perl    | 5.40.2   | <br />
  262. | PHP     | 8.3.19   | <br />
  263. | Vim     | 9.1.83   |
  264. ]]>
  265. </content>
  266. </entry>
  267. <entry xmlns="http://purl.org/atom/ns#">
  268. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1426/" />
  269. <title mode="escaped">Javascript: Returning data from an AJAX call</title>
  270. <modified>2025-05-28T19:59:48-07:00</modified>
  271. <issued>2025-05-28T19:59:48-07:00</issued>
  272. <created>2025-05-28T19:59:48-07:00</created>
  273. <id>http://www.perturb.org/display/entry/1426/</id>
  274. <summary type="text/plain"></summary>
  275. <author>
  276. <name>Scott Baker</name>
  277. <url>http://www.perturb.org/</url>
  278. <email>scott@perturb.org</email>
  279. </author>
  280. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  281. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  282.  
  283. Javascript is by it's nature asynchronous, which makes returning data from an AJAX call complicated. Modern Javascript uses the concept of a "[promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)" to allow you to run code after an asynchronous call competes. This is similar to using a callback function, but it reads cleaner. JQuery implements this type of call with the [`then()`](https://api.jquery.com/deferred.then/) function. A simple example is as follows: <br />
  284. <br />
  285. ```javascript <br />
  286. function getData() { <br />
  287.    return $.ajax({ <br />
  288.        url: '/api/data' <br />
  289.    }); <br />
  290. } <br />
  291. <br />
  292. // Usage <br />
  293. getData().then(function(data) { <br />
  294.    console.log(data); <br />
  295. }); <br />
  296. ```
  297. ]]>
  298. </content>
  299. </entry>
  300. <entry xmlns="http://purl.org/atom/ns#">
  301. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1425/" />
  302. <title mode="escaped">PHP: Generate secure password hashes from the CLI</title>
  303. <modified>2025-05-24T20:13:35-07:00</modified>
  304. <issued>2025-05-24T20:13:35-07:00</issued>
  305. <created>2025-05-24T20:13:35-07:00</created>
  306. <id>http://www.perturb.org/display/entry/1425/</id>
  307. <summary type="text/plain"></summary>
  308. <author>
  309. <name>Scott Baker</name>
  310. <url>http://www.perturb.org/</url>
  311. <email>scott@perturb.org</email>
  312. </author>
  313. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  314. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  315.  
  316. The `password_hash()` function in PHP is excellent for storing passwords securely. In order to generate password to store in a database or config file I like to generate passwords from the CLI. This has the risk of storing the password in your bash history. This command prompts you for the password on the fly and protects your history. <br />
  317. <br />
  318. ```bash <br />
  319. php -r 'echo "Password: "; $pwd = trim(fgets(STDIN)); echo password_hash($pwd, PASSWORD_DEFAULT) . "\n";' <br />
  320. ```
  321. ]]>
  322. </content>
  323. </entry>
  324. <entry xmlns="http://purl.org/atom/ns#">
  325. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1424/" />
  326. <title mode="escaped">Vim: Insert a line of characters</title>
  327. <modified>2025-04-01T00:00:00-07:00</modified>
  328. <issued>2025-04-01T00:00:00-07:00</issued>
  329. <created>2025-04-01T00:00:00-07:00</created>
  330. <id>http://www.perturb.org/display/entry/1424/</id>
  331. <summary type="text/plain"></summary>
  332. <author>
  333. <name>Scott Baker</name>
  334. <url>http://www.perturb.org/</url>
  335. <email>scott@perturb.org</email>
  336. </author>
  337. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  338. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  339.  
  340. I need an 80 character divider of text in Vim. I can never remember the sequence so I'm writing it down: <br />
  341. <br />
  342. ``` <br />
  343. 80i/<ESC> <br />
  344. ``` <br />
  345. <br />
  346. Will generate: <br />
  347. <br />
  348. ```text <br />
  349. //////////////////////////////////////////////////////////////////////////////// <br />
  350. ```
  351. ]]>
  352. </content>
  353. </entry>
  354. <entry xmlns="http://purl.org/atom/ns#">
  355. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1423/" />
  356. <title mode="escaped">Comparing 32bit and 64bit performance on low end micro-controllers</title>
  357. <modified>2025-03-05T13:47:09-08:00</modified>
  358. <issued>2025-03-05T13:47:09-08:00</issued>
  359. <created>2025-03-05T13:47:09-08:00</created>
  360. <id>http://www.perturb.org/display/entry/1423/</id>
  361. <summary type="text/plain"></summary>
  362. <author>
  363. <name>Scott Baker</name>
  364. <url>http://www.perturb.org/</url>
  365. <email>scott@perturb.org</email>
  366. </author>
  367. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  368. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  369.  
  370. Testing 32bit vs 64bit PRNGs on a 32bit ESP32-C3 [I'm seeing](https://gist.github.com/scottchiefbaker/e4c87de8d6c1ad4a33b1ffe5a3ce707f): <br />
  371. <br />
  372. | PRNG          | Iterations per second | Output Bits | Bytes per second | <br />
  373. | ------------- | --------------------- | ----------- | ---------------- | <br />
  374. | pcg32         | 487802                | 32          | **1951266.7 b/s**| <br />
  375. | xoroshiro64** | **516023**            | 32          | 2050966.7 b/s    | <br />
  376. | xoshiro256+   | 487808                | 64          | **3878726.7 b/s**| <br />
  377. | xoshiro512++  | 441735                | 64          | 3514373.3 b/s    | <br />
  378. | splitmix64    | 462290                | 64          | 3677033.3 b/s    | <br />
  379. | pcg64         | **416297**            | 64          | 3313060.0 b/s    | <br />
  380. <br />
  381. Very little difference on PRNGs that use 64bit operations vs 32bit operations. Even on limited hardware like this it makes sense to use a 64bit PRNG because you get more bytes per cycle.
  382. ]]>
  383. </content>
  384. </entry>
  385. <entry xmlns="http://purl.org/atom/ns#">
  386. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1422/" />
  387. <title mode="escaped">Vim: Convert your syntax highlighted text into HTML</title>
  388. <modified>2025-02-26T00:00:00-08:00</modified>
  389. <issued>2025-02-26T00:00:00-08:00</issued>
  390. <created>2025-02-26T00:00:00-08:00</created>
  391. <id>http://www.perturb.org/display/entry/1422/</id>
  392. <summary type="text/plain"></summary>
  393. <author>
  394. <name>Scott Baker</name>
  395. <url>http://www.perturb.org/</url>
  396. <email>scott@perturb.org</email>
  397. </author>
  398. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  399. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  400.  
  401. Vim is my code editor of choice as it has great features, excellent syntax highlighting, and a robust plug-in infrastructure. I'm very used to look and feel of Vim. If you want to share some of your code online, converting things to HTML can be problematic. Luckily Vim has a built in code to HTML converter: <br />
  402. <br />
  403. ``` <br />
  404. :TOhtml <br />
  405. ``` <br />
  406. <br />
  407. Simply run the `:TOhtml` command in an open text file and your buffer will be redrawn in HTML which you can then save. Here is a quick sample of my pcg32.pl script [converted to HTML](https://www.perturb.org/code/pcg32.pl.html).
  408. ]]>
  409. </content>
  410. </entry>
  411. <entry xmlns="http://purl.org/atom/ns#">
  412. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1421/" />
  413. <title mode="escaped">What kind of number makes a good seed for a PRNG?</title>
  414. <modified>2025-02-20T00:00:00-08:00</modified>
  415. <issued>2025-02-20T00:00:00-08:00</issued>
  416. <created>2025-02-20T00:00:00-08:00</created>
  417. <id>http://www.perturb.org/display/entry/1421/</id>
  418. <summary type="text/plain"></summary>
  419. <author>
  420. <name>Scott Baker</name>
  421. <url>http://www.perturb.org/</url>
  422. <email>scott@perturb.org</email>
  423. </author>
  424. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  425. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  426.  
  427. [Pseudo-random number generators](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) use complex math to generate random numbers on your computer. These random numbers are used for all sorts of things: simulations, fractals, games, art, and even math experiments. Computers can **only** do math, which makes generating a random number difficult.  <br />
  428. <br />
  429. PRNGs need a "seed" number to kick off the math that generates sequences of random numbers. Some PRNGs require a 32bit seed, and some require a 64bit seed. Some PRNGs require one seed, and some require four (or more). It is important to know what type of seed your PRNG needs. <br />
  430. <br />
  431. A 32bit number is between 0 and 4.2 billion and a 64bit number is between 0 and 18.4 quintillion. The larger a number is, the more bits are required to store it, and the better a seed it will make. The closer your seed is to the upper end of the number range the better. As a general rule a good seed will be a decimal number with 18 or 19 digits. <br />
  432. <br />
  433. `12` is a small number and **not** a good seed, `4611686018427387906` is a big number but still not a great seed. Seeds should **not** have large sections of zero/one bits. This is why small numbers do not make good seeds. Bits can be visualized by printing the number in binary: <br />
  434. <br />
  435. ```bash <br />
  436. # Horrible <br />
  437. $ perl -E 'printf("%064b\n", 4611686018427387906)' <br />
  438. 0100000000000000000000000000000000000000000000000000000000000010 <br />
  439. <br />
  440. # Bad <br />
  441. $ perl -E 'printf("%064b\n", 17770)' <br />
  442. 0000000000000000000000000000000000000000000000000100010101101010 <br />
  443. <br />
  444. # Poor <br />
  445. $ perl -E 'printf("%064b\n", 2850756010)' <br />
  446. 0000000000000000000000000000000010101001111010110001010110101010 <br />
  447. <br />
  448. # Good <br />
  449. $ perl -E 'printf("%064b\n", 11337502976607798025)' <br />
  450. 1001110101010110111001101110001101111000101001000100001100001001 <br />
  451. ``` <br />
  452. <br />
  453. Good seeds should have a _roughly_ even mix of zero and one bits. `9223372036854775808` is a large number and looks promising but it has 63 zeros, and only a single one bit. You can visualize the quality of your seed with [seed_quality.pl](https://www.perturb.org/code/seed_quality.pl). Quality above 75% should make for good seed numbers. <br />
  454. <br />
  455. Seeds should **not** be predictable. Do not use dates, times, or phone numbers as they are potentially guessable. Combinations of numbers can be good sources. Process PID, UID, unixtime are good potential sources _if_ they are combined together in a non-predictable way. PID multiplied by UID multiplied by Unixtime is an example of combining values. Memory locations of variables, especially if [ASLR](https://en.wikipedia.org/wiki/Address_space_layout_randomization) is in use is a potentially good source as well. <br />
  456. <br />
  457. Hashing numbers, strings, or combinations of numbers can be a good way to generate seeds. Hashing a value with [Komihash](https://github.com/scottchiefbaker/perl-Crypt-Komihash) or [xxHash](https://metacpan.org/pod/Digest::xxHash) will generate a suitable 64bit number. Hashing a value with [SHA256](https://metacpan.org/pod/Digest::SHA) will generate a 256bit value which can be [split](https://www.perturb.org/display/1415_Perl_Using_sha256_to_hash_strings_into_integers.html) into four 64bit values. Hashing functions also do a good job of ensuring the bits are mixed well and do not include large repeating sections. <br />
  458. <br />
  459. The best source of seed numbers is directly from your OS. On Linux this is `/dev/urandom` and on Windows you can interface with the `RtlGenRandom` API. These are carefully curated sources of _true_ randomness, but they can be slow-ish. Using them as a source for a fast PRNG is best practice. <br />
  460. <br />
  461. ```perl <br />
  462. sub get_64bit_seed { <br />
  463.    open my $urandom, '<:raw', '/dev/urandom' or croak("Couldn't open /dev/urandom: $!"); <br />
  464.    sysread($urandom, my $buf, 8) or croak("Couldn't read from csprng: $!"); <br />
  465. <br />
  466.    return unpack("Q*", $buf); <br />
  467. } <br />
  468. ```
  469. ]]>
  470. </content>
  471. </entry>
  472. <entry xmlns="http://purl.org/atom/ns#">
  473. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1420/" />
  474. <title mode="escaped">Perl: Multiply-Shift Hash</title>
  475. <modified>2025-01-27T00:00:00-08:00</modified>
  476. <issued>2025-01-27T00:00:00-08:00</issued>
  477. <created>2025-01-27T00:00:00-08:00</created>
  478. <id>http://www.perturb.org/display/entry/1420/</id>
  479. <summary type="text/plain"></summary>
  480. <author>
  481. <name>Scott Baker</name>
  482. <url>http://www.perturb.org/</url>
  483. <email>scott@perturb.org</email>
  484. </author>
  485. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  486. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  487.  
  488. I've been using the multiply-shift hash lately and have had good results. It's simple, fast, and well tested.  <br />
  489. <br />
  490. ```c <br />
  491. // Multiply-Shift Hash <br />
  492. static uint64_t hash_msh(uint64_t x) { <br />
  493.    uint64_t prime = 0x9e3779b97f4a7c15; // A large prime constant <br />
  494.    x ^= (x >> 30); <br />
  495.    x *= prime; <br />
  496.    x ^= (x >> 27); <br />
  497.    x *= prime; <br />
  498.    x ^= (x >> 31); <br />
  499.    return x; <br />
  500. } <br />
  501. ``` <br />
  502. <br />
  503. Whenever I find interesting code like this I like to try and implement it in Perl: <br />
  504. <br />
  505. ```perl <br />
  506. sub hash_msh { <br />
  507.    my $x     = $_[0]; <br />
  508.    my $prime = 11400714819323198485; <br />
  509.     <br />
  510.    $x ^= ($x >> 30); <br />
  511.    $x = multiply_uv($x, $prime); <br />
  512.    $x ^= ($x >> 27); <br />
  513.    $x = multiply_uv($x, $prime); <br />
  514.    $x ^= ($x >> 31); <br />
  515. <br />
  516.    return $x; <br />
  517. } <br />
  518. <br />
  519. # Perl converts numbers larger than 2^64 - 1 to floating point so <br />
  520. # we 'use integer' to force integer math which retains any overflow. <br />
  521. sub multiply_uv { <br />
  522.    my ($one, $two) = @_; <br />
  523. <br />
  524.    use integer; <br />
  525.    my $ret = $one * $two; <br />
  526.    no integer; <br />
  527. <br />
  528.    # Convert signed IV to unsinged UV <br />
  529.    if ($ret < 0) { <br />
  530.        $ret += 18446744073709551615; <br />
  531.        $ret += 1; <br />
  532.    } <br />
  533. <br />
  534.    return $ret; <br />
  535. } <br />
  536. ```
  537. ]]>
  538. </content>
  539. </entry>
  540. <entry xmlns="http://purl.org/atom/ns#">
  541. <link rel="alternate" type="text/html" href="http://www.perturb.org/display/entry/1419/" />
  542. <title mode="escaped">Perl: Calculate number of bits needed to store a number</title>
  543. <modified>2025-01-27T00:00:00-08:00</modified>
  544. <issued>2025-01-27T00:00:00-08:00</issued>
  545. <created>2025-01-27T00:00:00-08:00</created>
  546. <id>http://www.perturb.org/display/entry/1419/</id>
  547. <summary type="text/plain"></summary>
  548. <author>
  549. <name>Scott Baker</name>
  550. <url>http://www.perturb.org/</url>
  551. <email>scott@perturb.org</email>
  552. </author>
  553. <content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.perturb.org">
  554. <![CDATA[<link rel="stylesheet" type="text/css" media="screen" href="/css/rss-feed.css" title="Default" />
  555.  
  556. Quick Perl function to calculate the number of bits required to store a given number. <br />
  557. <br />
  558. ```perl <br />
  559. sub bits_required { <br />
  560.    my ($n) = @_; <br />
  561.     <br />
  562.    # Handle special case for 0 <br />
  563.    return 0 if $n == 0; <br />
  564. <br />
  565.    # Use logarithm to calculate the number of bits <br />
  566.    my $bits = int(log($n) / log(2)) + 1; <br />
  567.    return $bits; <br />
  568. } <br />
  569. ```
  570. ]]>
  571. </content>
  572. </entry>
  573. </feed>
  574.  
Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda