<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>John D. Cook</title>
	<atom:link href="http://www.johndcook.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.johndcook.com/blog</link>
	<description>Applied Mathematics Consulting</description>
	<lastBuildDate>Thu, 17 Sep 2026 19:47:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.johndcook.com/wp-content/uploads/2020/01/cropped-favicon_512-32x32.png</url>
	<title>John D. Cook</title>
	<link>https://www.johndcook.com/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Empirical fractal</title>
		<link>https://www.johndcook.com/blog/2026/09/17/empirical-fractal/</link>
					<comments>https://www.johndcook.com/blog/2026/09/17/empirical-fractal/#respond</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Thu, 17 Sep 2026 16:48:14 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Geometry]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247924</guid>

					<description><![CDATA[<p>There&#8217;s a common saying in discussion of fractals that the length of a coastline depends on how small a device you use to measure it. I thought this was a hypothetical, say as applied to the steps in the construction of the Koch snowflake. But the saying has its roots in actually surveying. Lewis Fry [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/17/empirical-fractal/">Empirical fractal</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>There&#8217;s a common saying in discussion of fractals that the length of a coastline depends on how small a device you use to measure it. I thought this was a hypothetical, say as applied to the steps in the construction of the Koch snowflake. But the saying has its roots in actually surveying.</p>
<p>Lewis Fry Richardson (1881–1953) noticed that the length of the coast of Scotland depended on a the size of segments used to measure it. More specifically, he found that the length followed a power law, i.e. that there&#8217;s a linear relation between the log of the coastline length and the log of the ruler length.</p>
<p>Here&#8217;s a reproduction of Richardson&#8217;s plot, taken from [1].</p>
<p><img fetchpriority="high" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/scottish_coast.png" width="500" height="351" /></p>
<p>Mandelbrot built on Richardson&#8217;s observation and defined the idea of fractal dimension.</p>
<p>I was under the impression that fractals were invented as mathematical novelties that researchers later found applications for. But as is often the case, the applications came first. Or at least <em>some</em> applications came first.</p>
<p>Ideally there&#8217;s always a feedback cycle where applications lead to theory and theory leads to applications. As Donald Knuth put it, &#8220;The best theory is inspired by practice. The best practice is inspired by theory.&#8221;</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2025/09/04/minimalist-mandelbrot-set/">Minimalist Mandelbrot set</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2021/07/11/fractal-brownian-motion/">The fractal nature of Brownian motion</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2025/08/16/randomly-generated-dragon/">Randomly generated dragon</a></li>
</ul>
<p>[1] Eoghan Bradley and Mark McCartney. Four hundred years of the fractal coastline of Scotland. The Mathematical Gazette, November 2019, Vol. 103, No. 558 (November 2019), pp. 518-521</p>The post <a href="https://www.johndcook.com/blog/2026/09/17/empirical-fractal/">Empirical fractal</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/17/empirical-fractal/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Phone words</title>
		<link>https://www.johndcook.com/blog/2026/09/17/phone-words/</link>
					<comments>https://www.johndcook.com/blog/2026/09/17/phone-words/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Thu, 17 Sep 2026 14:03:51 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247915</guid>

					<description><![CDATA[<p>I recently bought a copy of Los Alamos Rolodex, a book displaying business cards from Los Alamos Nation Labs from 1967 to 1978. You can find some examples of the cards here. One of the cards in the book is for Eugene Frank, President of B &#38; F Instruments. His card lists his phone number [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/17/phone-words/">Phone words</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>I recently bought a copy of Los Alamos Rolodex, a book displaying business cards from Los Alamos Nation Labs from 1967 to 1978. You can find some examples of the cards <a href="https://clui.org/collections/los-alamos-business-cards/selection-cards">here</a>.</p>
<p>One of the cards in the book is for Eugene Frank, President of B &amp; F Instruments. His card lists his phone number as</p>
<p style="padding-left: 40px;">(215) MErcury 9-7100</p>
<p>At first glance I thought the &#8220;E&#8221; in &#8220;MErcury&#8221; had been accidentally capitalized. Then I realized the intention was that someone would dial ME (i.e. 63) and ingore &#8220;rcury&#8221;. So the phone number would be (215) 639-7100.</p>
<p>This card was from 1968, the height of the space race. Presumably the card was alluding to the Project Mercury or the planet Mercury, or both.</p>
<p>The telephone keypad mapping (ITU E.161 standard) is a poor attempt at making phone numbers more memorable. For starters, there&#8217;s no way to encode 0 or 1 [1]. It&#8217;s unlikely a phone number will correspond to anything memorable unless you come up with the word first and then try to obtain the phone number, such as 800 FLOWERS.</p>
<p>Inserting extra letters, as Mr. Frank did, greatly increases the chances of encoding a phone number as a word. But then you need to denote which letters count and which ones are filler, so there&#8217;s not much advantage. Still, I wanted to play around with it for fun. I found 109 words [1] containing the letters from a telephone encoding of 4228646. (I&#8217;m using the file <code>/usr/share/dict/words</code> on my laptop as my list of words.)</p>
<p>Here are some of the more interesting hits.</p>
<ul>
<li>semicatholicism</li>
<li>heartburning</li>
<li>gladiatorism</li>
<li>diabetogenic</li>
<li>galactogenetic</li>
<li>xanthocreatinine</li>
</ul>
<p>There are over 30,000 words containing an encoding of the area code 832. One of these is <em>traditional</em>, and so I could write my phone number as</p>
<p style="padding-left: 40px;"><code>TraDitionAl semICAThOlIcisM</code>.</p>
<p>Another choice for 832 is <em>intercosmic</em>, so</p>
<p style="padding-left: 40px;"><code>inTErCosmic GAlaCTOGeNetic</code></p>
<p>is another possibility.</p>
<p><em>Galactogentic</em> can refer to the production of milk by the mammary glands or to the formation of galaxies (e.g. the Milky Way). Here <em>intercosmic</em> fits with the later sense.</p>
<p>I got greedy and tried to find a word containing the full phone number, 8324228646, but didn&#8217;t find anything.</p>
<p>Here&#8217;s my business card in the style of the Los Alamos Rolodex cards, created by Grok, using (832) GlAdiATOrIsM as the phone number.</p>
<p><img decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/vintage_card.png" width="600" height="366" /></p>
<p>Now suppose you remembered &#8220;gladiatorism&#8221; but not which letters were capitalized. Then you&#8217;d have to try up to 792, i.e. 12 choose 7, possible numbers, so this really isn&#8217;t a practical mnemonic. If you remembered &#8220;traditional semicatholicism&#8221; without capitalization it would be worse, with over a million possibilities (11 choose 3 times 15 choose 7). Some possibilities are counted twice, since different ways of selecting letters can lead to the same phone number, but still there are too many possibilities to try. </p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2021/07/26/major-memory-keypad/">Major memory system telephone keypad</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2023/11/17/phone-number-intel/">What can you learn from a phone number?</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2022/03/14/phone-tones-in-musical-notation/">Phone tones inn musical notation</a></li>
</ul>
<p>[1] Not only are there no letters for 0 and 1, the letters O and I represent digits. At one point in time the first digit of an exchange (the middle three digits) could not be a 0 or 1, but these digits could appear anywhere else.</p>
<p>[2] I initially found a list of 185 words, but some of these were duplicates: a word can represent a phone number in more than one way.</p>The post <a href="https://www.johndcook.com/blog/2026/09/17/phone-words/">Phone words</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/17/phone-words/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Converting between cosine similarity and concentration ratio</title>
		<link>https://www.johndcook.com/blog/2026/09/16/concentration-ratio/</link>
					<comments>https://www.johndcook.com/blog/2026/09/16/concentration-ratio/#respond</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 16:05:11 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Geometry]]></category>
		<category><![CDATA[Machine learning]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247909</guid>

					<description><![CDATA[<p>I&#8217;ve written three posts on cosine similarity lately. The first looked at interpreting cosine similarity. The second looked at an approximation related to the first. The third looked at how ranking according to cosine similarity works better than cosine similarity itself. Normalized word vectors are points on a high dimensional sphere, and geometry in high [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/16/concentration-ratio/">Converting between cosine similarity and concentration ratio</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve written three posts on cosine similarity lately. The <a href="https://www.johndcook.com/blog/2026/09/15/cosine-similarity/">first</a> looked at interpreting cosine similarity. The <a href="https://www.johndcook.com/blog/2026/09/15/simple-approximation-for-spherical-cap-area/">second</a> looked at an approximation related to the first. The <a href="https://www.johndcook.com/blog/2026/09/16/coffee-milk-latte/">third</a> looked at how ranking according to cosine similarity works better than cosine similarity itself.</p>
<p>Normalized word vectors are points on a high dimensional sphere, and geometry in high dimensions is counterintuitive. See the first post in this series for an explanation.</p>
<p>The set of points within a given angular distance of a point on a hypersphere is called a <a href="https://www.johndcook.com/blog/2023/08/09/hypersphere-cap/">spherical cap</a>. The ratio of the area of this spherical cap to that of the whole sphere is called <strong>cap fraction</strong> or <strong>concentration ratio</strong>. Concentration ratio explains why a modest cosine similarity value corresponds to a tiny portion of the area of the sphere and should be interpreted as a close match.</p>
<p>For this post, I wanted to share a plot of concentration ratio as a function of cosine similarity.</p>
<p><img decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/concentration_ratio.png" width="480" height="360" /></p>
<p>This shows that moderate values of cosine similarity correspond to infinitesimal concentration ratios. And yet, as the third post linked at the top showed, word vectors are very unevenly distributed, and even extremely small regions of the sphere can contain multiple word vectors.</p>
<p>I only included cosine similarity values up to 0.8 because the function plotted above takes a nosedive for larger values, even on a logarithmic scale.</p>
<p>Here&#8217;s the Python code to make the plot, using the function <code>cap_fraction</code> from <a href="https://www.johndcook.com/blog/2026/09/15/simple-approximation-for-spherical-cap-area/">here</a>.</p>
<pre>
s = np.linspace(0, 0.8, 500)
plt.plot(s, cap_fraction(np.acos(s), 200))
plt.yscale("log")
plt.xlabel("cosine similarity")
plt.ylabel("concentration ratio")
plt.show()
</pre>The post <a href="https://www.johndcook.com/blog/2026/09/16/concentration-ratio/">Converting between cosine similarity and concentration ratio</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/16/concentration-ratio/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Coffee + milk ≠ latte</title>
		<link>https://www.johndcook.com/blog/2026/09/16/coffee-milk-latte/</link>
					<comments>https://www.johndcook.com/blog/2026/09/16/coffee-milk-latte/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 15:06:58 +0000</pubDate>
				<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Machine learning]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247906</guid>

					<description><![CDATA[<p>Yesterday I wrote about the canonical example of how vector embeddings of words add: “king” − “man” + “woman” ≈ “queen” This should be interpreted as saying that the word vector for king, minus the word vector for man, plus the word vector for woman, is in some sense close to the word vector for queen. This post will [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/16/coffee-milk-latte/">Coffee + milk ≠ latte</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p><a href="https://www.johndcook.com/blog/2026/09/15/cosine-similarity/">Yesterday</a> I wrote about the canonical example of how vector embeddings of words add:</p>
<p style="padding-left: 40px;">“king” − “man” + “woman” ≈ “queen”</p>
<p>This should be interpreted as saying that the word vector for <em>king</em>, minus the word vector for <em>man</em>, plus the word vector for <em>woman</em>, is in some sense close to the word vector for <em>queen</em>.</p>
<p>This post will look at another example. Is the expression</p>
<p style="padding-left: 40px;">&#8220;coffee&#8221; + &#8220;milk&#8221; ≈ &#8220;latte&#8221;</p>
<p>true in some sense?</p>
<h2>Notation</h2>
<p>In this post I will use &#8220;foo&#8221; to mean the vector embedding of the word <em>foo</em>.</p>
<h2>Coffee + milk</h2>
<p>The cosine similarity between &#8220;coffee&#8221; + &#8220;milk&#8221; and &#8220;latte&#8221; is about 0.63. And for reasons given in the previous post, this is a large value of cosine similarity. But there are 11 words that are more similar to &#8220;milk&#8221; + &#8220;coffee&#8221; than &#8220;latte&#8221;. Here are the top 12 matches in order.</p>
<ol>
<li>coffee</li>
<li>milk</li>
<li>tea</li>
<li>drink</li>
<li>chocolate</li>
<li>cream</li>
<li>breakfast</li>
<li>ice</li>
<li>beer</li>
<li>vanilla</li>
<li>starbucks</li>
<li>latte</li>
</ol>
<p>There are two questions to resolve. First, why isn&#8217;t <em>latte</em> one of the closest words? Second, why is the cosine similarity large even though <em>latte</em> is not one of the best matches?</p>
<h2>Concept arithmetic</h2>
<p>When word vector arithmetic works, as in the king and queen example, the vectors combine <em>concepts</em>. If you replace the male gender component of <em>king</em> with a female component, you get a vector close to the vector for <em>queen</em>.</p>
<p>But when you add the vectors for <em>milk</em> and <em>coffee</em>, you&#8217;re not adding concepts, you&#8217;re adding ingredients.</p>
<p>The concepts of <em>milk</em> and <em>coffee</em> are similar in that they&#8217;re both common beverages, as are tea and even beer. A latte is a beverage, but it&#8217;s not as common as milk, coffee, tea, or beer.</p>
<h2>Extremely uneven distribution</h2>
<p>If you divide word vectors by their norm, you get a point on a high-dimensional sphere. In the case of the glove-twitter-200 vector embedding, you get a point on a sphere in 200 dimensions. As explained in the earlier post, a fairly large cosine similarity corresponds to a tiny portion of the sphere&#8217;s surface area.</p>
<p>In the example of “king” − “man” + “woman”, the vector &#8220;queen&#8221; is the closest match (except for &#8220;king&#8221; itself).</p>
<p>But there are a lot of words whose vectors are within a tiny region around &#8220;coffee&#8221; + &#8220;milk&#8221;. And by tiny, I mean a region that accounts for a proportion of the sphere on the order of 10<sup>−23</sup>.</p>
<p>The glove-twitter-200 vector list contains vectors for 1.2 million words. If these vectors were roughly evenly distributed on the sphere when normalized, you&#8217;d expect each patch representing 10<sup>−6</sup> of the sphere to contain about a word or two. You wouldn&#8217;t expect a patch taking up 10<sup>−12 </sup>of the sphere to contain more than one word, and you certainly wouldn&#8217;t expect a patch taking up 10<sup>−23 </sup>of the sphere to contain 12 words [1].</p>
<h2>Rank order</h2>
<p>Rank order based on cosine similarity is more robust than cosine similarity itself. This is an example of a phenomenon that occurs regularly: a metric whose values are dubious might still rank things well. Naive Bayes is another example. It naively computes probabilities in a way that is blatantly wrong, and yet ranking things by these spurious probabilities works well in some cases.</p>
<p>The cosine similarity between “king” − “man” + “woman” and &#8220;queen&#8221; is roughly the same as the cosine similarity between &#8220;coffee&#8221; + &#8220;milk&#8221; and &#8220;latte.&#8221; But in the former example, rank order picks out <em>queen</em> as the best match; rank order works like you&#8217;d expect, because you&#8217;re working with attributes that can be decomposed.</p>
<h2>Dog + infant = puppy?</h2>
<p>I wouldn&#8217;t be surprised if the Anglo-Saxon word for <em>puppy</em> was something like <em>dogchild</em>. The language was full of colorful compound words, such as <em>hronrad</em> (&#8220;whale-road&#8221;) for the sea and <em>nosethyrl</em> (&#8220;nose-hole&#8221;) for nostril.</p>
<p>Here are the top ten matches for &#8220;dog&#8221; + &#8220;infant&#8221; along with their cosine similarities.</p>
<ol>
<li>dog, 0.819</li>
<li>infant, 0.809</li>
<li>toddler, 0.734</li>
<li>dogs, 0.697</li>
<li>puppy, 0.688</li>
<li>cat, 0.682</li>
<li>pet, 0.676</li>
<li>child, 0.671</li>
<li>newborn, 0.670</li>
<li>baby, 0.650</li>
</ol>
<p>This shows that &#8220;puppy&#8221; is close to &#8220;dog&#8221; + &#8220;infant&#8221;, both in terms of cosine similarity and rank order, though it&#8217;s not the closet.</p>
<p>This also shows that you have to take the addition of word vectors with a grain of salt. It&#8217;s no surprise that <em>puppy</em> was a good match, but it&#8217;s surprising that <em>cat</em> is nearly as good.</p>
<p>[1] I poked around a little to get an idea just how unevenly words are distributed. The closest pair of words is <em>jajaja</em> and <em>jajajaja</em> with a cosine similarity of 0.993. The most isolated word, meaning the word whose nearest neighbor is furthest away, the the Thai word <span lang="th">เคยไหม</span>. It&#8217;s nearest neighbor is the Russian word <span lang="ru">боль</span> with a cosine similarity of 0.283.</p>
<p>The glove-twitter-200 vectors were created from a corpus that is about half English and about other languages and strings of symbols that are not words in any language. Presumably <span lang="th">เคยไหม</span> would have a much closer neighbor in a corpus containing more Thai words.</p>
<p>I didn&#8217;t search the entire corpus, only the 50,000 most frequently occurring vectors, because a full search would require running an <em>O</em>(<em>N</em>²) search with <em>N</em> = 1,200,000.</p>The post <a href="https://www.johndcook.com/blog/2026/09/16/coffee-milk-latte/">Coffee + milk ≠ latte</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/16/coffee-milk-latte/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Fibonacci product</title>
		<link>https://www.johndcook.com/blog/2026/09/16/fibonacci-product/</link>
					<comments>https://www.johndcook.com/blog/2026/09/16/fibonacci-product/#respond</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 16 Sep 2026 12:04:09 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Number theory]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247901</guid>

					<description><![CDATA[<p>The product of four consecutive Fibonacci numbers equals the product of two consecutive integers. For example, 3 × 5 × 8 × 13 = 39 × 40. I ran across this theorem in a note [1] that says &#8220;The product of any four consecutive Fibonacci numbers is twice a triangular number.&#8221; Since triangular numbers have [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/16/fibonacci-product/">Fibonacci product</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>The product of four consecutive Fibonacci numbers equals the product of two consecutive integers.</p>
<p>For example,</p>
<p style="padding-left: 40px;">3 × 5 × 8 × 13 = 39 × 40.</p>
<p>I ran across this theorem in a note [1] that says &#8220;The product of any four consecutive Fibonacci numbers is twice a triangular number.&#8221; Since triangular numbers have the form <em>n</em>(<em>n</em> + 1)/2, twice a triangular number is the product of two consecutive integers.</p>
<p>The note also gives a way to find the numbers on the right hand side. We have</p>
<p style="padding-left: 40px;"><em>F</em><sub><em>n</em></sub> <em>F</em><sub><em>n</em>+1</sub> <em>F</em><sub><em>n</em>+2</sub> <em>F</em><sub><em>n</em>+3</sub> = <em>m</em>(<em>m</em> + 1)</p>
<p>where <em>m</em> equals</p>
<p style="padding-left: 40px;"><em>F</em><sub><em>n</em>+1</sub> <em>F</em><sub><em>n</em>+2</sub></p>
<p>if <em>n</em> is odd and</p>
<p style="padding-left: 40px;"><em>F</em><sub><em>n</em></sub> <em>F</em><sub><em>n</em>+3</sub></p>
<p>if <em>n</em> is even.</p>
<p>In the example at the top, 3 is the 4th Fibonacci number, so <em>n</em> = 4. Since 4 is even, <em>m</em> is the product of the 4th and 7th Fibonacci numbers, i.e. <em>m</em> = 3 × 13 = 39.</p>
<h2>More Fibonacci posts</h2>
<ul>
<li class='link'><a href='https://www.johndcook.com/blog/2018/07/13/fibonacci-meets-pythagoras/'>Fibonacci meets Pythagoras</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2026/02/05/fibonacci-certificate/'>Certified Fibonacci numbers</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2025/10/17/trig-fibonacci/'>Turning trig identities into Fibonacci identities</a></li>
</ul>
<p>[1] K. B. Subramaniam. On a link between Triangular and Fibonacci numbers. The Mathematical Gazette, Vol. 103, No. 558 (November 2019), p. 489.</p>The post <a href="https://www.johndcook.com/blog/2026/09/16/fibonacci-product/">Fibonacci product</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/16/fibonacci-product/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Simple approximation for spherical cap area</title>
		<link>https://www.johndcook.com/blog/2026/09/15/simple-approximation-for-spherical-cap-area/</link>
					<comments>https://www.johndcook.com/blog/2026/09/15/simple-approximation-for-spherical-cap-area/#respond</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Tue, 15 Sep 2026 22:00:44 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Geometry]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247896</guid>

					<description><![CDATA[<p>The previous post looked at how to interpret cosine similarity, or equivalently angles between word vectors. In a high-dimensional space, randomly chosen vectors are likely nearly perpendicular, and so relatively large angles, such as 50°, indicate very closely related words. Another way to look at this, as explained in the previous post, is that in [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/15/simple-approximation-for-spherical-cap-area/">Simple approximation for spherical cap area</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>The <a href="https://www.johndcook.com/blog/2026/09/15/cosine-similarity/">previous post</a> looked at how to interpret cosine similarity, or equivalently angles between word vectors. In a high-dimensional space, randomly chosen vectors are likely nearly perpendicular, and so relatively large angles, such as 50°, indicate very closely related words.</p>
<p>Another way to look at this, as explained in the previous post, is that in high dimensions, a spherical cap of angular radius θ represents a small portion of a sphere, even for moderately large θ.</p>
<p>The proportion of the area inside the spherical cap, given <a href="https://www.johndcook.com/blog/2023/08/09/hypersphere-cap/">here</a>, involves the &#8220;regularized incomplete beta function&#8221; and so it&#8217;s hard to have an intuition for the value.</p>
<p>For large dimension <em>n</em>, the approximation</p>
<p style="padding-left: 40px;"><em>n</em><sup>−1/2</sup> sin<sup><em>n</em> − 1</sup>(θ)</p>
<p>gives the proportion of the area inside the cap to within an order of magnitude. It&#8217;s easy to see that this function goes to zero quickly as <em>n</em> increases, provided |θ| &lt; π/2.</p>
<p>If you have the cosine similarity <em>c</em> = cos θ rather than θ itself, the approximation becomes</p>
<p style="padding-left: 40px;"><em>n</em><sup>−1/2</sup> (1 − <em>c</em>²)<sup>(<em>n</em> − 1)/2</sup>.</p>
<h2>Python script</h2>
<p>Let&#8217;s try it on the example from the previous post, in which <em>n</em> = 200 and θ = 49°.</p>
<pre>import numpy as np
from scipy.special import betainc

# Fraction of S^{n-1} inside a spherical cap of angular radius theta
# theta is measured from the pole
# Assume 0 &lt; theta &lt; pi/2

def cap_fraction(theta, n):
    x = np.sin(theta) ** 2
    return 0.5 * betainc(0.5 * (n - 1), 0.5, x)

def cap_fraction_approx(theta, n):
    return n**(-0.5) * np.sin(theta)**(n-1)

theta = np.deg2rad(49)
print(cap_fraction(theta, 200)) 
print(cap_fraction_approx(theta, 200)) 
</pre>
<p>This prints 2.03e-26 and 3.37e-26. The order of magnitude is correct as advertised.</p>The post <a href="https://www.johndcook.com/blog/2026/09/15/simple-approximation-for-spherical-cap-area/">Simple approximation for spherical cap area</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/15/simple-approximation-for-spherical-cap-area/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>What counts as a large cosine similarity?</title>
		<link>https://www.johndcook.com/blog/2026/09/15/cosine-similarity/</link>
					<comments>https://www.johndcook.com/blog/2026/09/15/cosine-similarity/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Tue, 15 Sep 2026 16:06:02 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Differential geometry]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247894</guid>

					<description><![CDATA[<p>Machine learning represents words as vectors and measures the similarity of words by the angles between the vectors. For vectors x and y, where θ is the angle between the vectors, and so This is the cosine similarity between the words represented by x and y. Small angles have large cosines, and so words with larger cosine similarities [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/15/cosine-similarity/">What counts as a large cosine similarity?</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Machine learning represents words as vectors and measures the similarity of words by the angles between the vectors.</p>
<p>For vectors <strong>x</strong> and <strong>y</strong>,</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" style="background-color: white;" src="https://www.johndcook.com/dotproduct3.svg" alt="\mathbf{x} \cdot \mathbf{y} = ||\mathbf{x} || \,||\mathbf{y} || \, \cos(\theta)" width="173" height="18" /></p>
<p>where θ is the angle between the vectors, and so</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" style="background-color: white;" src="https://www.johndcook.com/dotproduct4.svg" alt="\cos(\theta) = \frac{\mathbf{x} \cdot \mathbf{y}}{ ||\mathbf{x} || \,||\mathbf{y} || }" width="136" height="37" /></p>
<p>This is the cosine similarity between the words represented by <strong>x</strong> and <strong>y</strong>.</p>
<p>Small angles have large cosines, and so words with larger cosine similarities are closer together than words with smaller cosine similarities. The cosine similarity between a word and itself equals 1, and we&#8217;d expect unrelated words to have a cosine similarity near 0.</p>
<p>You can do a sort of arithmetic with vector embeddings of words. The canonical example is that</p>
<p style="padding-left: 40px;">&#8220;king&#8221; − &#8220;man&#8221; + &#8220;woman&#8221; ≈ &#8220;queen&#8221;</p>
<p>Implicit in this equation is that we&#8217;re really adding vector representations of the words. Let <strong>a</strong>, <strong>b</strong>, <strong>c</strong>, and <strong>d</strong> be the vector embeddings of the words <em>king</em>, <em>man</em>, <em>woman</em>, and <em>queen</em>. What we&#8217;re really asserting is that</p>
<p style="padding-left: 40px;"><strong>a</strong> − <strong>b</strong> + <strong>c</strong> ≈ <strong>d</strong>,</p>
<p>except that&#8217;s not true! Or at least it&#8217;s not true unless you view it in the right context.</p>
<p>The angle between <strong>a</strong> − <strong>b</strong> + <strong>c</strong> and <strong>d</strong> is about 49°, which corresponds to a cosine similarity of 0.656. Here I&#8217;m using the gensim glove-twitter-200 embedding that represents words as 200-dimensional vectors.</p>
<p>The way to interpret the equation above is not that a 49° degree angle is approximately 0, or that a similarity of 0.656 is approximately 1.</p>
<p>In high dimensions, such as 200-dimensional word embeddings, nearly all vectors are nearly perpendicular. I wrote a post about this <a href="https://www.johndcook.com/blog/2023/08/09/random-points-hypersphere-orthant/">here</a>. So the angle between randomly selected words will usually be close to 90°, and so in that context an angle of 49° is relatively small. For example, the angle between the vector representations of <em>king</em> and <em>fireplace</em> is 89.25°.</p>
<p>If you divide word vectors by their norm, you can think of each vector as a point on a high-dimensional sphere, in our case a sphere in 200 dimensions. The proportion of vectors within 49° of a given point is surprisingly small in high dimensions.</p>
<p>Let&#8217;s say our point of interest is the north pole of an <em>n</em>-dimensional sphere. We&#8217;d like to calculate the proportion of the area of the sphere that is within an angle θ of the pole. I go through the calculations <a href="https://www.johndcook.com/blog/2023/08/09/hypersphere-cap/">here</a>. (Update: I give an approximation <a href="https://www.johndcook.com/blog/2026/09/15/simple-approximation-for-spherical-cap-area/">here</a> that&#8217;s easier to work with than the exact formula.)</p>
<p>When <em>n</em> = 3, 17% of the area is with 49 degrees of the pole. But when <em>n</em> = 200, the proportion is on the order of 10<sup>−26</sup>, essentially zero.</p>
<p>The vector <strong>d</strong> above representing <em>queen</em> is within a relatively tiny region around the vector <strong>a</strong> − <strong>b</strong> + <strong>c</strong>.</p>
<p>In terms of cosine similarity, 0.656 is a large similarity. Words with a cosine similarity in this range are quite close, even though we wouldn&#8217;t normally think of 0.656 being close to 1. In this context, 0.656 <em>is</em> close to 1.</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2023/08/08/angles-between-words/">Angles between words</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2023/08/09/hypersphere-cap/">Area and volume of a hypersphere cap</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2023/08/09/cosine-similarity-not-a-metric/">Cosine similarity does not satisfy the triangle inequality</a></li>
</ul>The post <a href="https://www.johndcook.com/blog/2026/09/15/cosine-similarity/">What counts as a large cosine similarity?</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/15/cosine-similarity/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Guessing the meaning of a number</title>
		<link>https://www.johndcook.com/blog/2026/09/14/guessing-the-meaning-of-a-number/</link>
					<comments>https://www.johndcook.com/blog/2026/09/14/guessing-the-meaning-of-a-number/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Mon, 14 Sep 2026 10:44:45 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247892</guid>

					<description><![CDATA[<p>Suppose I give you an n-digit number and ask you what it represents. This seems impossible, and in theory it is impossible. But in practice it&#8217;s often possible. Apps on a phone may automatically interpret a 10-digit number as a phone number or a 16-digit number as a package tracking number. And very often these interpretations are [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/14/guessing-the-meaning-of-a-number/">Guessing the meaning of a number</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Suppose I give you an <em>n</em>-digit number and ask you what it represents. This seems impossible, and in theory it <em>is</em> impossible. But in practice it&#8217;s often possible.</p>
<p>Apps on a phone may automatically interpret a 10-digit number as a phone number or a 16-digit number as a package tracking number. And very often these interpretations are correct, given the kinds of things most people use their phones for.</p>
<p>It&#8217;s not surprising that a 10-digit number <em>on a phone</em> is a <em>phone number</em>. It&#8217;s more interesting that a 16-digit number is likely a tracking number. It could be other things, such as a credit card number. But people don&#8217;t usually write out credit card numbers in a text note; credit card numbers likely saved in some more opaque way.</p>
<p>I run into a variation of this problem routinely, trying to infer what a number represents inside medical notes.</p>
<p>A five-digit number could be a US postal code, or it could be a <a href="https://www.johndcook.com/blog/2022/09/23/hcpcs-codes/">medical procedure code</a>.</p>
<p>A six-digit number could be a date in MMDDYY format, or it could be a medical record number.</p>
<p>A ten-digit number could be a phone number, or it could be an <a href="https://www.johndcook.com/blog/2024/06/26/npi-number/">NPI</a> (National Provider Identifier) number.</p>
<p>It&#8217;s interesting that it&#8217;s possible make a good guess at what a number means inside unstructured text. Context has been lost, but not all context: you know you&#8217;re looking at medical notes. And that meager bit of context can be surprisingly useful.</p>The post <a href="https://www.johndcook.com/blog/2026/09/14/guessing-the-meaning-of-a-number/">Guessing the meaning of a number</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/14/guessing-the-meaning-of-a-number/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Bayesian OCR</title>
		<link>https://www.johndcook.com/blog/2026/09/10/bayesian-ocr/</link>
					<comments>https://www.johndcook.com/blog/2026/09/10/bayesian-ocr/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Thu, 10 Sep 2026 12:32:31 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Bayesian]]></category>
		<category><![CDATA[Typography]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247884</guid>

					<description><![CDATA[<p>The Greek letter β (beta) and the German letter ß (eszett) look similar, especially in some fonts. Now suppose an OCR program sees some character that could be a beta or could be an eszett. It could calculate some kind of distance between between the pixel pattern of the character and the pixel patterns of [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/10/bayesian-ocr/">Bayesian OCR</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>The Greek letter β (beta) and the German letter ß (eszett) look similar, especially in some fonts.</p>
<p>Now suppose an OCR program sees some character that could be a beta or could be an eszett. It could calculate some kind of distance between between the pixel pattern of the character and the pixel patterns of beta and eszett. But that would be discarding context.</p>
<p>If you&#8217;re scanning a Greek document and run into a beta-like symbol, it&#8217;s very likely a beta. If you&#8217;re scanning a German document and run into a beta-like symbol, it <em>could</em> be a beta. For example, it could be a scientific paper that mentions beta particles or beta carotene. But most likely the symbol is an eszett.</p>
<p>The previous paragraph is saying you should compute the <em>conditional</em> probability of a set of pixels representing a character <em>given</em> the language of the document. You could be more sophisticated and look at the position of the symbol in a word as well. For example, if you see a symbol at the end of a Greek word that could either be ο (omicron) or σ (sigma), it&#8217;s likely an omicron because Greek has a different symbol ς for final sigma.</p>
<p>This post is a follow-on to my <a href="https://www.johndcook.com/blog/2026/09/07/ngram-error-rate/">earlier post</a> on the error rate in Google&#8217;s Ngram database. OCR errors are fairly common in that database, so why don&#8217;t they &#8220;just&#8221; fix the errors by using some sort of Bayesian method? OCR software probably does use some sort of Bayesian method, but it&#8217;s not that simple.</p>
<p>In that post I looked at the use of the word <em>grok</em> in English. The Ngram database shows the word being used before it was coined in 1961 due to OCR errors. Why didn&#8217;t Google compute the probability of a word being &#8220;grok&#8221; conditional on the publication date? That would be circular. We happen to know exactly when <em>grok</em> was coined, but in general we might try to determine when a word was coined by looking at a large set of scanned books, like the Ngram database!</p>
<p>Now we could compute the probable value of an ambiguously scanned word by conditioning on the language of the surrounding text. That would be a reasonable thing to do in general, but it could also lead to exactly the kind of errors we see in the Ngram data for <em>grok</em>.</p>
<p>Suppose you see an ambiguously scanned word in a book written in English. There is a higher prior probability that the word is an English word than a German word. Now suppose you see &#8220;gro?&#8221; where ? could be β, ß, or k. Without any context, perhaps the probability of the symbol being a <em>k</em> is small. But <em>grok</em> is an English word and groß is a German word which may lead you to conclude &#8220;?&#8221; is a <em>k</em> and the ambiguous word is <em>grok</em>.</p>
<p>Assigning higher prior probability to English words in English texts is the best thing to do <em>on average</em>, but in particular instances it will lead to errors. That&#8217;s life.</p>
<p>The Ngram database includes millions of scanned books. Google had to use OCR algorithms that work well on average. A linguist with a special interest in a particular word can be more careful and create a more sophisticated probability model (explicit or implicit) customized for their interests. Google did what they could operating at such a large scale.</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2025/08/14/uppercase-eszett/">Uppercase eszett</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2011/09/27/bayesian-amazon/">A Bayesian view of Amazon resellers</a></li>
</ul>The post <a href="https://www.johndcook.com/blog/2026/09/10/bayesian-ocr/">Bayesian OCR</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/10/bayesian-ocr/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>A 50-year-old computer-assisted proof</title>
		<link>https://www.johndcook.com/blog/2026/09/09/four-colors/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 09 Sep 2026 14:59:48 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247877</guid>

					<description><![CDATA[<p>The idea of using computers to assist with proofs is not new. The first major computer-assisted proof was published in 1976, the proof of the four color theorem by Kenneth Appel and Wolfgang Haken. The authors reduced the proof of the four color theorem to verifying calculations on 1,834 configurations, each checked by a computer [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/09/four-colors/">A 50-year-old computer-assisted proof</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>The idea of using computers to assist with proofs is not new. The first major computer-assisted proof was published in 1976, the proof of the four color theorem by Kenneth Appel and Wolfgang Haken. The authors reduced the proof of the four color theorem to verifying calculations on 1,834 configurations, each checked by a computer program.</p>
<p>The proof was simplified over the years, and formalized in Coq in 2005. Everyone is satisfied that the theorem is true, but there has never been a satisfying proof, one that a human could read and say &#8220;I see now why any map can be colored using only four colors.&#8221; And there may never be one, but see <a href="https://www.johndcook.com/blog/2013/09/04/homework-problems-for-2090/">this post</a> for a contrary prediction.</p>
<p>The IBM mainframe that ran the calculations completing the proof of the four color theorem did not generate the proof. It simply executed the FORTRAN program that Haken and Appel (and Koch [1]) gave it.</p>
<p>I don&#8217;t see the recent proof of finite-time blowup for solutions to the Navier-Stokes equations as entirely different. Computers did higher-level tasks for the OpenAI team than the mainframe did for Haken and Appel, and these tasks were not as directly programmed as the tasks that were given to the mainframe, but still machines do what they are told to do.</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2013/07/19/the-seven-color-map-theorem/">The seven color map theorem</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2019/09/12/detecting-typos/">Detecting errors with the four color theorem</a></li>
</ul>
<p>[1] John A. Koch was a programmer who worked on the four color proof with Haken and Appel. I don&#8217;t know how much credit he deserves, but I suspect it may be more than he was given.</p>The post <a href="https://www.johndcook.com/blog/2026/09/09/four-colors/">A 50-year-old computer-assisted proof</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>AI is an intelligence multiplier</title>
		<link>https://www.johndcook.com/blog/2026/09/09/ai-multiplier/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 09 Sep 2026 14:17:20 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247875</guid>

					<description><![CDATA[<p>A rising tide may lift all boats, but the AI tide lifts some boats much more than others. By all accounts, the best programmers have had the biggest productivity boost from AI. And top tier mathematicians are using AI to settle long-standing mathematical conjectures. AI is a powerful tool, but tools don&#8217;t come to life [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/09/ai-multiplier/">AI is an intelligence multiplier</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>A rising tide may lift all boats, but the AI tide lifts some boats much more than others.</p>
<p>By all accounts, the best programmers have had the biggest productivity boost from AI. And top tier mathematicians are using AI to settle long-standing mathematical conjectures. AI is a powerful tool, but tools don&#8217;t come to life and make things on their own.</p>
<p>I routinely have naive amateurs [1] send me proofs of open conjectures, and naturally more recent such proofs involve AI. I&#8217;ll get an email saying something like &#8220;I&#8217;ve solved the Collatz conjecture using ChatGPT, but I&#8217;m not a mathematician so I need some help verifying the proof.&#8221; And of course the supposed proof is rubbish.</p>
<p>The recent Navier-Stokes proof is impressive, but AI didn&#8217;t initiate the proof any more than LaTeX did. Nor did a child steer AI into proving the conjecture. Professional mathematicians were able to use AI to pursue their ideas at superhuman speed. But someone without an understanding of the Navier-Stokes problem, and familiarity with recent ideas for approaching the problem, could not have directed AI to produce a proof.</p>
<p>Computer scientists have been saying &#8220;garbage in, garbage out&#8221; from the beginning. A variation on this aphorism for the age of AI would be &#8220;mediocrity in, mediocrity out.&#8221;</p>
<p style="text-align: center;">***</p>
<p>[1] Amateurs can and do make contributions to mathematics. For example, in 2022 David Smith, a retired print technician, discovered a single shape that can be used to create an aperiodic tiling of the plane. By &#8220;naive amateurs&#8221; I mean people who literally do not know what they are talking about.</p>The post <a href="https://www.johndcook.com/blog/2026/09/09/ai-multiplier/">AI is an intelligence multiplier</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The part of Navier-Stokes no one is talking about</title>
		<link>https://www.johndcook.com/blog/2026/09/09/formal-method-revolution/</link>
					<comments>https://www.johndcook.com/blog/2026/09/09/formal-method-revolution/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 09 Sep 2026 12:43:36 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Formal methods]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247870</guid>

					<description><![CDATA[<p>Yesterday OpenAI announced a proof that settled a long-standing question about the Navier-Stokes equations from fluid dynamics. The announcement has created a lot of buzz, as one would expect. But there&#8217;s an aspect of OpenAI&#8217;s work that I haven&#8217;t seen anyone talk about: they posted a Lean 4 formal proof at the same time as [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/09/formal-method-revolution/">The part of Navier-Stokes no one is talking about</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Yesterday OpenAI announced a proof that settled a long-standing question about the Navier-Stokes equations from fluid dynamics. The announcement has created a lot of buzz, as one would expect. But there&#8217;s an aspect of OpenAI&#8217;s work that I haven&#8217;t seen anyone talk about: they posted a Lean 4 formal proof at the same time as their conventional human-readable proof.</p>
<p>Quite a few other mathematical conjectures have been settled recently using AI, and these have also been accompanied with formal proofs, using Lean 4 in particular.</p>
<p>Until very recently, generating machine-verifiable formal proofs has been <strong>excruciatingly tedious</strong>. In 2005, Henk Barendregt and Freek Wiedijk <a href="https://www.cs.ru.nl/~freek/notes/RSpaper.pdf">wrote</a></p>
<blockquote><p>To give an indication of how much work is needed for formalisation, we estimate that it takes approximately one work-week (five work-days of eight work-hours) to formalise one page from an undergraduate mathematics textbook.</p></blockquote>
<p>That was the rule of thumb: <strong>forty hours per page</strong>. And this in the context of undergraduate textbooks. Research publications are much denser than textbooks. Furthermore, page 100 of a textbook probably depends mostly on material on pages 1 through 99. A sentence in a research article could cite anything that has been published before.</p>
<p>Say a research article takes 20 times more effort to formalize than page in an undergraduate textbook. Then formalizing the 166-page paper from OpenAI would take 132,800 person-hours. It took OpenAI 17 hours to verify their proof in Lean. I hesitate to use the word &#8220;revolutionary,&#8221; but lowering the cost of anything by <strong>four orders of magnitude</strong> is revolutionary.</p>
<p>I&#8217;ve used AI to generate formal proofs to check my work just for a little blog post. I wouldn&#8217;t dream of doing that if I had to pay someone a week&#8217;s salary to check my work.</p>
<p>Formal verification doesn&#8217;t just apply to mathematics. You could, for example, formally verify that a set of security policies are consistent and that, given certain assumptions, they accomplish their purpose. You could formally verify that a smart contract imposes a certain maximum liability. You could verify the correctness of mission-critical algorithms. These problems are easier than formalizing mathematics research, and it is easier to quantify the return on investment.</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2025/12/24/automation-and-validation/">Automation and validation</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2016/07/11/formal-methods-let-you-explore-the-corners/">Formal methods let you explore the corners</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2020/12/03/formal-proof-roi/">When are formal methods worth the effort?</a></li>
</ul>The post <a href="https://www.johndcook.com/blog/2026/09/09/formal-method-revolution/">The part of Navier-Stokes no one is talking about</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/09/formal-method-revolution/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Navier-Stokes in the news</title>
		<link>https://www.johndcook.com/blog/2026/09/08/navier-stokes-in-the-news/</link>
					<comments>https://www.johndcook.com/blog/2026/09/08/navier-stokes-in-the-news/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Tue, 08 Sep 2026 15:26:08 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[Differential equations]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247864</guid>

					<description><![CDATA[<p>There are rumors that a long-standing math problem, one of the Millennium Prize problems, has been solved. The problem concerns technical properties of solutions to the Navier-Stokes equations [1], a set of equations that describe the dynamics of fluid flow. Popular accounts of the problem are often oversimplified and misleading. Some reports will speak of [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/08/navier-stokes-in-the-news/">Navier-Stokes in the news</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>There are rumors that a long-standing math problem, one of the Millennium Prize problems, has been solved.</p>
<p>The problem concerns technical properties of solutions to the <strong>Navier-Stokes equations</strong> [1], a set of equations that describe the dynamics of fluid flow. Popular accounts of the problem are often oversimplified and misleading.</p>
<p>Some reports will speak of the problem as &#8220;solving the Navier-Stokes equations.&#8221; The task is not to write down a closed-form solution, which can&#8217;t be done, or solve the equations numerically, which has been done for decades. The problem is to prove theoretical properties of solutions which are of little interest in practice.</p>
<p>There has been progress toward settling the Navier-Stokes problem. Terence Tao wrote a post on this <a href="https://terrytao.wordpress.com/2026/09/07/finite-time-blowup-with-smooth-forcing-term-for-the-incompressible-porous-medium-boussinesq-and-incompressible-euler-equations/">yesterday</a>.</p>
<p>What&#8217;s also  interesting is the intrigue around the possible solution. A <a href="https://x.com/etale27/status/2097190864598560892">post</a> this morning says</p>
<blockquote><p>If I am reading this correctly, Tristan Buckmaster is alleging OAI has a resolution of Navier-Stokes … which maybe used info from Buckmaster and Levent Alpöge’s private Codex sessions.</p></blockquote>
<p>Buckmaster asked OpenAI whether they used his private sessions and they have not responded. <strong>Update</strong>: <a href="https://openai.com/index/navier-stokes-solution/">Statement</a> from OpenAI.</p>
<h2>Personal note</h2>
<p>This topic connects parts of my career spanning decades. My graduate work was in PDEs and I had some interest in the Navier-Stokes equations. Here are some <a href="https://www.johndcook.com/NavierStokes.pdf">notes</a> I wrote back in the day.</p>
<p>Now I work more with privacy than with PDEs. The question of whether OpenAI uses private data, contradicting their stated policy, is more relevant to my current work than whether the Navier-Stokes equations have global regular solutions.</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2014/08/04/engineering-a-waterpark/">Engineering a waterpark</a></li>
<li class="link"><a href="https://www.johndcook.com/Euler_Lagrange_Equations.pdf">Euler-Lagrange equations</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/data-privacy/">Data privacy</a></li>
</ul>
<p>[1] I never know whether to say equation or equations. You&#8217;ll hear both. You could think of Navier-Stokes as one vector-valued PDE or three scalar-valued equations.</p>The post <a href="https://www.johndcook.com/blog/2026/09/08/navier-stokes-in-the-news/">Navier-Stokes in the news</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/08/navier-stokes-in-the-news/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Ngram error rate</title>
		<link>https://www.johndcook.com/blog/2026/09/07/ngram-error-rate/</link>
					<comments>https://www.johndcook.com/blog/2026/09/07/ngram-error-rate/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Mon, 07 Sep 2026 18:35:45 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247861</guid>

					<description><![CDATA[<p>The Online Etymological Dictionary gives the following etymology for grok: grok (v.) &#8220;understand empathically,&#8221; 1961, an arbitrary formation by U.S. science fiction writer Robert A. Heinlein (1907-1988) in his book &#8220;Stranger in a Strange Land.&#8221; In the book it is a transliteration of a Martian word and is said to mean etymologically &#8220;to drink.&#8221; It attained [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/07/ngram-error-rate/">Ngram error rate</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p><span class="hyphens-auto" lang="en">The Online Etymological Dictionary gives the following etymology for <em>grok</em>:</span></p>
<blockquote><p>grok (v.)</p>
<p>&#8220;understand empathically,&#8221; 1961, an arbitrary formation by U.S. science fiction writer Robert A. Heinlein (1907-1988) in his book &#8220;Stranger in a Strange Land.&#8221; In the book it is a transliteration of a Martian word and is said to mean etymologically &#8220;to drink.&#8221; It attained popular use in 1960s-70s counterculture but is perhaps obsolete now except in internet technology circles.</p></blockquote>
<p>I don&#8217;t believe anything in the statement above is disputed. And yet Google&#8217;s Ngram Viewer tells a very different story.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/grok_ngram.png" width="600" height="220" /></p>
<p>The plot implies that use of the word <em>grok</em> had been increasing before Heinlein&#8217;s book came out and is now much more common than it was in the 1970s. Note that the plot ends before the Grok AI came out in late 2023.</p>
<p>Apparently the Ngram data is unreliable, mainly for two reasons: OCR errors and inaccurate date attribution. Presumably the blip around 1900 was due to the former, OCR causing words like <em>crok</em> or <em>grog</em> to be cataloged as <em>grok</em>. And presumably the rise in usage before 1961 was due to the latter, misattributing the date of sources published after 1961.</p>
<p>The supposed rise in usage before 1961 is interesting. You&#8217;d expect some lag between the time a word circulates in conversation and when it appears in books, but apparently this lag can be smaller than the effect of date misattribution.</p>
<p>Etymonline speculates that <em>grok</em> is &#8220;perhaps obsolete now except in internet technology circles.&#8221; That matches my experience. Even in technological circles, the word was uncommon before Grok was released. Maybe it was more common in print than in conversation.</p>
<h2>Related posts</h2>
<p>Previous posts with Ngram stats. The effects are so large that they&#8217;re probably directionally correct after adjusting for a substantial error rate.</p>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2021/04/18/duodecimal/">Duodecimal vs. Hexadecimal</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2013/06/07/orwellian-vs-huxleyian/">Orwellian vs. Huxleyian</a></li>
</ul>The post <a href="https://www.johndcook.com/blog/2026/09/07/ngram-error-rate/">Ngram error rate</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/07/ngram-error-rate/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Proof of the rank-trace theorem</title>
		<link>https://www.johndcook.com/blog/2026/09/05/proof-of-the-rank-trace-theorem/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sat, 05 Sep 2026 17:04:13 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Linear algebra]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247858</guid>

					<description><![CDATA[<p>The previous post discussed the motivation for and application of the rank-trace theorem. This post will give a proof. Suppose A is a real symmetric matrix. The rank-trace inequality says where tr is the trace operator, the sum of the elements along the diagonal of the matrix. Terse proof Here&#8217;s the proof in a nutshell: diagonalize A [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/05/proof-of-the-rank-trace-theorem/">Proof of the rank-trace theorem</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>The <a href="https://www.johndcook.com/blog/2026/09/04/stable-rank/">previous post</a> discussed the motivation for and application of the rank-trace theorem. This post will give a proof.</p>
<p>Suppose <em>A</em> is a real symmetric matrix. The rank-trace inequality says</p>
<p><img loading="lazy" decoding="async" class="aligncenter" src="https://www.johndcook.com/rank_trace1.svg" alt="\operatorname{rank}(A)\ge\frac{(\operatorname{tr} A)^2}{\operatorname{tr}(A^2)}" width="143" height="49" /></p>
<p>where tr is the trace operator, the sum of the elements along the diagonal of the matrix.</p>
<h2>Terse proof</h2>
<p>Here&#8217;s the proof in a nutshell: diagonalize <em>A</em> and use the Cauchy-Schwarz inequality.</p>
<h2>Detailed proof</h2>
<p>Now let&#8217;s unpack that. Any real symmetric matrix <em>A</em> is similar to a matrix <em>D</em> with the eigenvalues of <em>A</em> along the diagonal.</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/rank_trace2.svg" alt="A = PDP^{-1}" width="91" height="18" /></p>
<p>The trace of a matrix stays the same under a similarity transformation, i.e. multiplying by <em>P</em> on one side and its inverse on the other side. So without loss of generality we may as well assume <em>A</em> is diagonal.</p>
<p>The rank of a matrix equals the number of non-zero eigenvalues, so a vector containing the non-zero eigenvalues of <em>A</em></p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/rank_trace3.svg" alt="v = [\lambda_1, \lambda_2, \ldots, \lambda_r]" width="147" height="17" /></p>
<p>has length <em>r</em> where <em>r</em> is the rank of <em>A</em>. Define <em>w</em> to be the vector of dimension <em>r</em> consisting of all 1&#8217;s.</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/rank_trace4.svg" alt="w = [1, 1, \ldots, 1]" width="130" height="17" /></p>
<p>Then by the Cauchy-Schwarz inequality we have</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/rank_trace6.svg" alt="\operatorname{tr}(A)^2 = \langle v, w \rangle^2 \leq \langle v, v \rangle \, \langle w, w \rangle = r \operatorname{tr}(A^2)" width="332" height="22" /></p>
<h2>Cyclic trace property</h2>
<p>Why should a matrix <em>A</em> and its diagonalization <em>D</em> have the same trace?</p>
<p>The trace of a matrix product <em>AB</em> equals the trace of the product <em>BA</em>. To prove this, write out matrix products and the traces, then note that the two expressions are equal.</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/trace_commute.svg" alt=" \begin{align*} \operatorname{tr}(AB) &amp;= \sum_i(AB)_{ii}=\sum_i\sum_k A_{ik}B_{ki} \\ \operatorname{tr}(BA) &amp;= \sum_j(BA)_{jj}=\sum_j\sum_k B_{jk}A_{kj} \end{align*}" width="291" height="98" /></p>
<p>Therefore</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/rank_trace7.svg" alt="\operatorname{tr}(A) = \operatorname{tr}((PD)P^{-1}) = \operatorname{tr}(P^{-1}(PD)) = \operatorname{tr}(D)" width="351" height="22" /></p>
<p>More generally, trace has the cyclic property</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/cycle_trace.svg" alt="\operatorname{tr}(ABC) = \operatorname{tr}(CAB) = \operatorname{tr}(BCA)" width="242" height="18" /></p>
<p>However, not all permutations preserve the trace. For example, let</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/rank_trace8.svg" alt="A=\begin{pmatrix}0&amp;1\\0&amp;0\end{pmatrix},\quad B=\begin{pmatrix}0&amp;0\\1&amp;0\end{pmatrix},\quad C=\begin{pmatrix}1&amp;0\\0&amp;0\end{pmatrix}." width="342" height="48" /></p>
<p>Then</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/rank_trace11.svg" alt="\operatorname{tr}(ABC) = \operatorname{tr}\begin{pmatrix}1&amp;0\\0&amp;0\end{pmatrix} = 1" width="192" height="48" /></p>
<p>but</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/rank_trace10.svg" alt="\operatorname{tr}(ACB) = \operatorname{tr}\begin{pmatrix}0&amp;0\\0&amp;0\end{pmatrix} = 0" width="192" height="48" /></p>The post <a href="https://www.johndcook.com/blog/2026/09/05/proof-of-the-rank-trace-theorem/">Proof of the rank-trace theorem</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Computing a lower bound on matrix rank</title>
		<link>https://www.johndcook.com/blog/2026/09/04/stable-rank/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Fri, 04 Sep 2026 14:16:16 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[Linear algebra]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247851</guid>

					<description><![CDATA[<p>Suppose you want to know the rank of an n × n matrix A, the number of linearly independent rows of A, or equivalently the number of linearly independent columns. There are at least three difficulties. Difficulties in computing rank First of all, rank is not a continuous function of a matrix. Since rank is an [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/04/stable-rank/">Computing a lower bound on matrix rank</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Suppose you want to know the rank of an <em>n</em> × <em>n</em> matrix <em>A</em>, the number of linearly independent rows of <em>A</em>, or equivalently the number of linearly independent columns. There are at least three difficulties.</p>
<h2>Difficulties in computing rank</h2>
<p>First of all, rank is not a continuous function of a matrix. Since rank is an integer, an arbitrarily small change in the matrix could cause a discrete change in the rank [1]. A small error in computing <em>A</em> could produce a matrix with a different rank.</p>
<p>Second, finding the rank takes <em>O</em>(<em>n</em>³) operations, which may or may not be an issue depending on context.</p>
<p>Third, you may not have the matrix <em>A</em> in an explicit form. Maybe you&#8217;re able to compute products <em>Av</em> for vectors <em>v</em> but it&#8217;s not practical to form the entire matrix <em>A</em>.</p>
<h2>Rank-trace inequality</h2>
<p>If you don&#8217;t need to know the rank of <em>A</em> per se, but only need to know whether it is above a certain size, a lower bound on the rank may enough.</p>
<p>Suppose <em>A</em> is a Hermitian matrix. If <em>A</em> is real, this means <em>A</em> is symmetric. If <em>A</em> is complex, this means <em>A</em> equals its conjugate transpose. Then the rank-trace inequality says</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/rank_trace1.svg" alt="\operatorname{rank}(A)\ge\frac{(\operatorname{tr} A)^2}{\operatorname{tr}(A^2)}" width="143" height="49" /><br />
The quantity on the right hand side is known as the <strong>stable rank</strong> of <em>A</em>. It&#8217;s not a rank in any algebraic sense, but it gives a lower bound on rank. And it solves the three problems listed above. See the <a href="https://www.johndcook.com/blog/2026/09/05/proof-of-the-rank-trace-theorem/">next post</a> for a proof of the rank-trace theorem.</p>
<h3>Stability</h3>
<p>First of all, trace <em>is</em> a continuous function of a matrix, and so stable rank is also a continuous function of a matrix, provided the denominator isn&#8217;t zero. A small change to a matrix only makes a small change to its stable rank. That&#8217;s why stable rank is called stable.</p>
<h3>Efficiency</h3>
<p>Second, although computing rank takes <em>O</em>(<em>n</em>³) operations, computing stable rank takes only <em>O</em>(<em>n</em>²) operations, though this isn&#8217;t immediately obvious.</p>
<p>The trace of <em>A</em> takes <em>n</em> operations: simply sum the elements on the diagonal of <em>A</em>. But how do you take the trace of <em>A</em>²? Squaring <em>A</em> takes <em>n</em>³ operations, and so if you had to square <em>A</em> to find the trace of <em>A</em>² the rank-trace inequality would have no efficiency advantage over finding the rank of <em>A</em>. But you can compute the trace of <em>A</em>² via</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/trace_A2.svg" alt="\operatorname{tr}(A^2) = \sum_{i=1}^n \sum_{j=1}^n |a_{ij}|^2" width="171" height="57" /></p>
<h3>Formation</h3>
<p>Now suppose you don&#8217;t have the matrix <em>A</em> per se but you do have a way of probing <em>A</em>, computing the product of vectors with <em>A</em>. Maybe <em>A</em> is too large to fit into memory, or explicitly computing the elements of <em>A</em> would take too long.</p>
<p>There are Monte Carlo algorithms for estimating the traces of <em>A</em> and <em>A</em>² that could be used together to estimate the stable rank of <em>A</em>.</p>
<h2>Demonstration</h2>
<p>The following Python code illustrates the discussion above.</p>
<pre>import numpy as np

np.random.seed(20260904)
n = 5
B = np.random.randn(n, n)
A = B.T @ B + 1e-8 * np.eye(n)  # Gram matrix plus a tiny shift =&gt; SPD

rank_A = np.linalg.matrix_rank(A)
tr_A = np.trace(A)
tr_A2 = np.trace(A @ A) # matrix product 
sum_sq = np.sum(A * A) # element-by-element product
stable_rank = (tr_A ** 2) / tr_A2

print(f"A =\n{A}\n")
print(f"rank(A)              = {rank_A}")
print(f"tr(A)                = {tr_A:.12f}")
print(f"tr(A^2) direct       = {tr_A2:.12f}")
print(f"tr(A^2) indirect     = {sum_sq:.12f}")
print(f"stable rank          = {stable_rank:.12f}")
</pre>
<p>The code above produces the output below.</p>
<pre>A =
[[ 1.09945682  0.4899665   0.98901845  0.66983113 -1.35006341]
 [ 0.4899665   0.98531254  0.35067791  0.89757603 -0.72037507]
 [ 0.98901845  0.35067791  4.31233926  0.94556225 -0.54819048]
 [ 0.66983113  0.89757603  0.94556225  1.3494295  -1.33840786]
 [-1.35006341 -0.72037507 -0.54819048 -1.33840786  3.54858332]]

rank(A)              = 5
tr(A)                = 11.295121449420
tr(A^2) direct       = 51.035447533673
tr(A^2) indirect     = 51.035447533673
stable rank          = 2.499826585688
</pre>
<p>[1] Topological argument: A map from a connected space (such as ℝ<sup><em>n</em>×<em>n</em></sup>) onto a discrete space (such as ℤ) cannot be continuous, otherwise the inverse images of the points in the range would partition the connected space into disjoint open sets, violating the definition of a connected space.</p>The post <a href="https://www.johndcook.com/blog/2026/09/04/stable-rank/">Computing a lower bound on matrix rank</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Hugging Face Easter Egg</title>
		<link>https://www.johndcook.com/blog/2026/09/03/hugging-face-easter-egg/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Thu, 03 Sep 2026 23:34:41 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Unicode]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247847</guid>

					<description><![CDATA[<p>NVIDIA has offered to buy Hugging Face for $12,930,300,000. 129303 is the Unicode code point for the Hugging Face emoj (U+1F917), which you can verify with the following Python code. &#62;&#62;&#62; import unicodedata &#62;&#62;&#62; 129303 == 0x1F917 True &#62;&#62;&#62; unicodedata.name(chr(0x1F917)) 'HUGGING FACE' Related posts Prevent characters from displaying as emoji Unicode, Tolkien, and Privacy Unicode [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/03/hugging-face-easter-egg/">Hugging Face Easter Egg</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>NVIDIA has offered to buy Hugging Face for $12,930,300,000.</p>
<p>129303 is the Unicode code point for the Hugging Face emoj (U+1F917), which you can verify with the following Python code.</p>
<pre>
&gt;&gt;&gt; import unicodedata
&gt;&gt;&gt; 129303 == 0x1F917
True
&gt;&gt;&gt; unicodedata.name(chr(0x1F917))
'HUGGING FACE'
</pre>
<p><img loading="lazy" decoding="async" src="https://www.johndcook.com/huggingface.png" width="200" height="200" alt="Hugging Face emoji" class="aligncenter size-medium" /></p>
<h2>Related posts</h2>
<ul>
<li class='link'><a href='https://www.johndcook.com/blog/2022/09/30/preventing-emoji/'>Prevent characters from displaying as emoji</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2025/03/09/tengwar/'>Unicode, Tolkien, and Privacy</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2025/03/09/unicode-surrogates/'>Unicode surrogates</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2022/10/02/flags-unicode/'>Making flags in Unicode</a></li>
</ul>The post <a href="https://www.johndcook.com/blog/2026/09/03/hugging-face-easter-egg/">Hugging Face Easter Egg</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>New RSA number factored</title>
		<link>https://www.johndcook.com/blog/2026/09/03/new-rsa-number-factored/</link>
					<comments>https://www.johndcook.com/blog/2026/09/03/new-rsa-number-factored/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Thu, 03 Sep 2026 17:21:45 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Cryptography]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247845</guid>

					<description><![CDATA[<p>Eric Lu announced on X today that he has factored RSA-260, a number N with 260 digits (862 bits) that is the product of two large primes [1]. RSA numbers are challenge problems posed to gauge the security of RSA encryption, which rests on the difficulty of factoring large numbers [2]. The naming scheme is [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/09/03/new-rsa-number-factored/">New RSA number factored</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Eric Lu <a href="https://x.com/penlume/status/2095372672356212876?s=20">announced</a> on X today that he has factored RSA-260, a number <em>N</em> with 260 digits (862 bits) that is the product of two large primes [1].</p>
<p>RSA numbers are challenge problems posed to gauge the security of RSA encryption, which rests on the difficulty of factoring large numbers [2]. The naming scheme is confusing because RSA-<em>n</em> might have <em>n</em> digits or <em>n</em> bits. For example, RSA-768 is smaller than RSA-260 because the former has 768 bits and the latter has 260 digits.</p>
<p>RSA-260 is the largest RSA number factored so far. What does the news of its factorization say about the security of RSA?</p>
<p>Based on equations <a href="https://www.johndcook.com/blog/2025/09/30/time-needed-to-factor-large-integers/">here</a>, an RSA key with 862 bits would have a security level of 74 bits, i.e. the same security level as symmetric encryption with a 74-bit key. The minimum recommended RSA key size now is 2048 bits, which has a security level of 107 bits.</p>
<p>Security levels are on a logarithmic scale: each additional bit of security doubles the effort required to break the encryption by brute force. So breaking a 2048-bit RSA key would take 2<sup>34</sup>, roughly 10<sup>10</sup>, times more effort than factoring RSA-260. All this depends on numerous assumptions, such as the state of factorization algorithms and the non-existence of CRQC [3].</p>
<p><strong>Update</strong>: A week after the initial announcement, Eric Lu released an <a href="https://cognition.com/blog/factoring-rsa-260">article</a> explaining how he factored RSA-260. He says &#8220;In total, I estimate that this factorization cost about 4,900 GPU-days, or 13.5 GPU-years, which is about $400k at current market prices.&#8221;</p>
<h2>Related posts</h2>
<ul>
<li class="link"><a href="https://www.johndcook.com/blog/2019/02/11/rsa-duplication-flaws/">RSA implementation flaws</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2023/08/05/rsa-private-key/">Generating and inspecting an RSA key</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2025/08/05/martin-gardners-rsa/">Martin Gardner&#8217;s RSA article</a></li>
<li class="link"><a href="https://www.johndcook.com/blog/2026/06/13/rsa-munitions-t-shirt/">RSA munitions T-shirt</a></li>
</ul>
<p>[1] <em>N</em> = <em>pq</em> = 22112825529529666435281085255026230927612089502470015394413748319128822941402001986512729726569746599085900330031400051170742204560859276357953757185954298838958709229238491006703034124620545784566413664540684214361293017694020846391065875914794251435144458199</p>
<p><em>p</em> = 4397328654844826923795068102505872571721883526553349659561256924505973939597593482272505698004801207988043088656411102133523080581</p>
<p><em>q</em> = 5028695206842569864686141618253083416610081090075366674776775706538324961364412200138116378509733307971876652984898985905923678379</p>
<p>[2] The ability to efficiently factor large primes would break RSA. It&#8217;s possible that there&#8217;s a way to break RSA without being able to factor large numbers. More on that <a href="https://www.johndcook.com/blog/2025/01/06/rsa-factoring/">here</a>.</p>
<p>[3] Cryptographically-relevant quantum computer. Quantum computers exist, but so far they&#8217;re cryptographically irrelevant. So far quantum computers cannot factor 21 without <a href="https://www.johndcook.com/blog/2026/03/31/quantum-y2k/">cheating</a>.</p>The post <a href="https://www.johndcook.com/blog/2026/09/03/new-rsa-number-factored/">New RSA number factored</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/09/03/new-rsa-number-factored/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Patented application of linear algebra</title>
		<link>https://www.johndcook.com/blog/2026/08/31/patented-application-of-linear-algebra/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Mon, 31 Aug 2026 23:26:12 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Linear algebra]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247831</guid>

					<description><![CDATA[<p>I just found out Brian Beckman and I got a patent on work we did for GSI Technology [1]. Nearly all the work I do is under an NDA, so I don&#8217;t often get a chance to talk about my projects. This work is public now that it&#8217;s in a patent; I suppose it has [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/31/patented-application-of-linear-algebra/">Patented application of linear algebra</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>I just found out Brian Beckman and I got a patent on work we did for GSI Technology [1]. Nearly all the work I do is under an NDA, so I don&#8217;t often get a chance to talk about my projects. This work is public now that it&#8217;s in a patent; I suppose it has been public since the application was published.</p>
<p>Brian did most of the work on the project. My contribution was to mathematically formalize low-level operations on sheets of bits using linear algebra over a binary field. Lots of Hadamard products and outer products, if I remember correctly. When you can reduce computations to algebra, you can prove that a sequence of operations is correct, and you can find optimizations by simplifying expressions.</p>
<p>The patent mentions a programming language called Tartan. I suggested calling it plaid because it used matrices with mask patterns that reminded me of a plaid pattern, and Brian countered saying we should call it Tartan. I like that name better.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/tartan2.png" alt="Figure 5B from patent" width="550" height="514" /></p>
<p style="text-align: center;">Figure 5B from the patent.</p>
<p>[1] Brian Beckman and John D. Cook. Compiler for a parallel processor. U.S. Patent 12,717,871 B2. Applicant/Assignee: GSI Technology Inc., Sunnyvale, CA.</p>The post <a href="https://www.johndcook.com/blog/2026/08/31/patented-application-of-linear-algebra/">Patented application of linear algebra</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Making the unnecessary easier</title>
		<link>https://www.johndcook.com/blog/2026/08/28/making-the-unnecessary-easier/</link>
					<comments>https://www.johndcook.com/blog/2026/08/28/making-the-unnecessary-easier/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Fri, 28 Aug 2026 14:35:36 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247823</guid>

					<description><![CDATA[<p>I watched a few videos this morning, looking for ideas of what I could use AI to do. In one video, someone had an agent monitor tech news sites every 30 minutes to notify him of a variety of developments. No doubt that&#8217;s less effort than visiting a bunch of sites every half hour, but [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/28/making-the-unnecessary-easier/">Making the unnecessary easier</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>I watched a few videos this morning, looking for ideas of what I could use AI to do.</p>
<p>In one video, someone had an agent monitor tech news sites every 30 minutes to notify him of a variety of developments. No doubt that&#8217;s less effort than visiting a bunch of sites every half hour, but not monitoring tech news in real time takes even less effort.</p>
<p>Another video mentioned having Grok Bot order a sandwich through DoorDash. If I want a sandwich, I make a sandwich.</p>
<p>One video showed how to manage dozens messaging services. Maybe you could just not use dozens of messaging services.</p>
<p>And of course there are videos on creating agents to monitor the agents that monitor your news, order your sandwiches, and manage your messages.</p>
<p>All the use cases I saw were ways to using technology mitigate problems caused by technology, making it easier to do things that don&#8217;t need to be done, or at least things that I don&#8217;t need to do.</p>
<p>Of course different people have different needs. Some people have a professional need to monitor news in real time, for example, and having an agent help with that could be big win. I suspect, however, that the use cases that you&#8217;ll see most often in YouTube videos have been made up to appeal to a wide audience rather than to scratch the author&#8217;s itch.</p>
<p>Productivity is deeply personal. As I said in an <a href="https://www.johndcook.com/blog/2023/06/03/productive-productivity/">earlier post</a>, the scripts I&#8217;ve found most useful are of <em>zero</em> interest to anyone else because they are so specific to my work. I&#8217;ve mostly automated tasks with Python and bash, not with AI.</p>
<p>I&#8217;m not trying to avoid using AI. As I said at the top of the post I&#8217;m looking for more ways to take advantage of it. But I don&#8217;t want to fall into the trap of doing more easily what doesn&#8217;t need to be done. Or, to put a finer point on it, I don&#8217;t want to find ways for <em>my business</em> to do things that <em>we</em> do not need to do, things that other businesses may need to do.</p>
<h2>Related posts</h2>
<ul>
<li class='link'><a href='https://www.johndcook.com/blog/2023/06/03/productive-productivity/'>Productive productivity</a></li>
<li class='link'><a href='https://www.johndcook.com/blog/2010/12/07/cascading-needs/'>Maybe you only need it because you have it</a></li>
</ul>The post <a href="https://www.johndcook.com/blog/2026/08/28/making-the-unnecessary-easier/">Making the unnecessary easier</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/28/making-the-unnecessary-easier/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Second solutions</title>
		<link>https://www.johndcook.com/blog/2026/08/27/second-solutions/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Thu, 27 Aug 2026 13:14:35 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Differential equations]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247814</guid>

					<description><![CDATA[<p>This post provides a couple examples to go along with two earlier posts. The pattern we&#8217;re illustrating is families of polynomials pn(x) that each satisfy a differential equation and a three-term recurrence. The differential equations have a second solution qn(x) that is the larger solution with respect to x but the smaller solution with respect to n. In both [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/27/second-solutions/">Second solutions</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>This post provides a couple examples to go along with two <a href="https://www.johndcook.com/blog/2026/08/26/junk-solutions/">earlier</a> <a href="https://www.johndcook.com/blog/2026/08/24/numerical-instability-recurrece/">posts</a>.</p>
<p>The pattern we&#8217;re illustrating is families of polynomials <em>p</em><sub><em>n</em></sub>(<em>x</em>) that each satisfy a differential equation and a three-term recurrence. The differential equations have a second solution <em>q</em><sub><em>n</em></sub>(<em>x</em>) that is the larger solution with respect to <em>x</em> but the smaller solution with respect to <em>n</em>.</p>
<p>In both the examples below <em>p</em><sub><em>n</em></sub>(<em>x</em>) is a polynomial, and so bounded on the interval [−1, 1], and <em>q</em><sub><em>n</em></sub>(<em>x</em>) is not a polynomial, with singularities at ±1. This is analogous to the previous examples with Bessel functions <em>J</em><sub><em>n</em></sub>(<em>x</em>) and <em>Q</em><sub><em>n</em></sub>(<em>x</em>) that satisfy the same differential equation but have contrasting behavior with respect to <em>x</em> versus <em>n</em>.</p>
<h2>Legendre polynomials</h2>
<p>The differential equation</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/legendre_de.svg" alt="(1-x^2)\,y^{\prime\prime} - 2x\,y^\prime + n(n+1)\,y = 0 " width="258" height="23" /></p>
<p>has two solutions for each <em>n</em>, <em>P</em><sub><em>n</em></sub>(<em>x</em>) and <em>Q</em><sub><em>n</em></sub>(<em>x</em>).</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/legendre_P_Q.png" width="600" height="450" /></p>
<p>The solutions <em>P</em><sub><em>n</em></sub>(<em>x</em>) are the Legendre polynomials. The solutions <em>Q</em><sub><em>n</em></sub>(<em>x</em>) are not polynomials but involve a term log((1 + <em>x</em>)/(1 − <em>x</em>)) that blows up at 1 and −1. But for fixed <em>x</em> and increasing <em>n</em>, <em>P</em><sub><em>n</em></sub>(<em>x</em>) grows exponentially and <em>Q</em><sub><em>n</em></sub>(<em>x</em>) decays exponentially, provided |<em>x</em>| &gt; 1.</p>
<h2>Chebyshev polynomials</h2>
<p>The differential equation</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/chebyshev_de.svg" alt="(1-x^2)\,y^{\prime\prime} - x\,y^\prime + n^2\,y = 0" width="204" height="23" /></p>
<p>has two solutions for each <em>n</em>, <em>T</em><sub><em>n</em></sub>(<em>x</em>) and <em>V</em><sub><em>n</em></sub>(<em>x</em>).</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/chebyshev_T_V.png" width="600" height="438" /></p>
<p>The solutions <em>T</em><sub><em>n</em></sub>(<em>x</em>) are the Chebyshev polynomials. The solutions <em>V</em><sub><em>n</em></sub>(<em>x</em>) are not polynomials but involve a term √(<em>x</em>² — 1) that become vertical up at 1 and −1. But for fixed <em>x</em> with |<em>x</em>| &gt; 1 and increasing <em>n</em>, <em>T</em><sub><em>n</em></sub>(<em>x</em>) grows exponentially and <em>V</em><sub><em>n</em></sub>(<em>x</em>) decays exponentially.</p>The post <a href="https://www.johndcook.com/blog/2026/08/27/second-solutions/">Second solutions</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What is the quality of software that AI writes?</title>
		<link>https://www.johndcook.com/blog/2026/08/26/what-is-the-quality-of-software-that-ai-writes/</link>
					<comments>https://www.johndcook.com/blog/2026/08/26/what-is-the-quality-of-software-that-ai-writes/#comments</comments>
		
		<dc:creator><![CDATA[Wayne Joubert]]></dc:creator>
		<pubDate>Wed, 26 Aug 2026 18:51:13 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Software development]]></category>
		<category><![CDATA[AI coding tools]]></category>
		<category><![CDATA[AI slop]]></category>
		<category><![CDATA[software quality]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247731</guid>

					<description><![CDATA[<p>AI-powered coding agents increase productivity for many developers. But do these agents produce good-quality code? Some say this doesn&#8217;t matter, we are heading toward dark software factories with source code never inspected, and maybe we should eliminate source code altogether&#8212;&#8220;source code is the new assembly code&#8221;. Others have a different view. Humans sometimes need to [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/26/what-is-the-quality-of-software-that-ai-writes/">What is the quality of software that AI writes?</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>AI-powered coding agents increase productivity for many developers. But do these agents produce good-quality code?</p>
<p>Some say this doesn&#8217;t matter, we are heading toward dark software factories with source code never inspected, and <a href="https://www.reddit.com/r/singularity/comments/1veslal/elon_musk_the_next_step_is_getting_rid_of_source/">maybe</a> we should <a href="https://x.com/elonmusk/status/2084304083851034949">eliminate</a> source code altogether&#8212;&#8220;source code is the new assembly code&#8221;.</p>
<p>Others have a different view. Humans sometimes need to debug source code. Source code may need to be audited by humans for compliance. Code should be clear enough for a human to inspect and reason about the algorithms and behavior. Also, good code quality can make the code more legible to agents and reduce unnecessary context.</p>
<p>Developer teams can have many different ideas of what constitutes high-quality software and good coding style. Though there are many valid ways to write code, there is also wide consensus on general <a href="https://blog.codacy.com/code-complexity">principles</a> of code quality. For example, avoiding very large single functions or modules, avoiding code duplication, avoiding undisciplined feature creep or patchy code and avoiding unnecessarily deep class hierarchies or function call chains. Some coding style choices are testable empirically for impact on developer productivity. Furthermore, some code complexity measures can be computed objectively and programmatically.</p>
<p>My experiences are with GPT 5.5 (Extra High reasoning) and 5.6 (Extra High, Max and occasionally Ultra). Much of my experience is &#8220;out of the box&#8221; usage of Codex, with simple AGENTS.md file, though I am working on <a href="https://openai.com/index/harness-engineering">improving</a> the engineering of guidance files, and it is helping. My source code is mostly Python. Unfortunately it is difficult to generalize any one set of experiences universally, since developers have different code bases, languages, models, harnesses and AGENTS.md files. One-shotting a simple computer game or website would be very different from developing a complex research code in a new domain.</p>
<p>At first glance, the AI-written code is not incomprehensible. It does not use odd variable names like &#8220;iiii&#8221; or &#8220;a87275,&#8221; and it does not look like it came out of an <a href="https://www.ioccc.org/">obfuscated code competition</a>. But, in my experience, still the generated code has deficiencies:</p>
<ul>
<li>The agent has a tendency to write much more code than is necessary (commonly 2-3X more&#8212;see also related findings <span style="color: #3366ff;"><a style="color: #3366ff;" href="https://arxiv.org/abs/2603.24755">here</a></span>). Though it is capable of deleting code, its primary impulse seems to be to write more code.</li>
<li>You can work with the agent to shorten the code, but it takes work. The agent it seems is not fluent in finding structural simplifications and then extracting commonalities. In one session I spent 1/2 hour having the agent write a few hundred lines of code, and 4 hours to get it to shorten and simplify the code. You can imagine the kind of technical debt this would accumulate.</li>
<li>It behaves as though code simplification is much more out of its reach than code generation. At times it just completely fails to do some simplification task I ask it to do.</li>
<li>It has no instinct for when to break a file into multiple files for conceptual clarity, even if a file becomes over 10,000 lines long.</li>
<li>It can reinvent a similar but different helper function in different code modules rather than designing a simple reusable function once.</li>
<li>It can make massive function argument lists with 10-20 arguments rather than recognizing that the parameters may form a coherent concept representable as an abstraction or parameter object.</li>
<li>Importantly, it can define functions based on abstractions that do not model the underlying domain well and are hard to decipher. When I called it on this, it said: &#8220;You’re right. The code is naming implementation mechanics instead of stating intent &#8230; it forces the reader to mentally execute several layers of infrastructure just to discover that it means.&#8221;</li>
<li>It often invents terminology that cannot instantly be understood by the reader (the source code analogy of <span style="color: #3366ff;"><a style="color: #3366ff;" href="https://sensible.com/dont-make-me-think/">Don&#8217;t Make Me Think</a></span>).</li>
<li>It can repeat the same expression multiple times instead of defining a variable with a meaningful name to represent the quantity.</li>
<li>It can hardwire unexplained “magic constants” into the code instead of defining them with meaningful names.</li>
</ul>
<p>Indeed, when pressed, the models are sometimes capable of doing better. For example, for a hard design problem, 5.6 Ultra was capable of creating a good object design that was a good match to the problem domain, when I asked it to look hard at the problem&#8212;better than the less sophisticated models.</p>
<p>I would certainly expect that with more engineering of the agent guidance files, many or most of these problems would get better. However, it should not require extreme measures to get coding agents to write good code.</p>
<p>I have not compared other coding agents, but it would not surprise me if they had similar issues. Rightly, the coding models have been optimized for their software development utility, and this has undoubtedly succeeded in a revolutionary way.</p>
<p>It seems there is not yet a widely accepted code-quality benchmark playing the role for frontier coding models that SWE-bench has played for software engineering capability (though there are <a href="https://labs.scale.com/leaderboard/sweatlas-refactoring">efforts</a>). It’s especially interesting because many aspects of code quality are verifiable, making the problem seemingly quite amenable to treatment in post-training. I am hoping that someone can put together a good benchmark for this problem, and that the frontier labs will embrace these kinds of evaluations in model development.</p>
<p>&nbsp;</p>The post <a href="https://www.johndcook.com/blog/2026/08/26/what-is-the-quality-of-software-that-ai-writes/">What is the quality of software that AI writes?</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/26/what-is-the-quality-of-software-that-ai-writes/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Junk solutions</title>
		<link>https://www.johndcook.com/blog/2026/08/26/junk-solutions/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 26 Aug 2026 12:16:17 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Differential equations]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247744</guid>

					<description><![CDATA[<p>When you&#8217;re interested in studying a family of functions, it can be useful to look at a differential equation that the functions solve. This is a theme I&#8217;ve written about several times, most recently here and here, but also three years ago here. Orthogonal polynomials are mathematically elegant as well as very useful in applications [1]. [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/26/junk-solutions/">Junk solutions</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>When you&#8217;re interested in studying a family of functions, it can be useful to look at a differential equation that the functions solve. This is a theme I&#8217;ve written about several times, most recently <a href="https://www.johndcook.com/blog/2026/08/10/inverse-differential-equations/">here</a> and <a href="https://www.johndcook.com/blog/2026/08/01/why-polynomial-coefficients/">here</a>, but also three years ago <a href="https://www.johndcook.com/blog/2023/07/04/useful-de/">here</a>.</p>
<p>Orthogonal polynomials are mathematically elegant as well as very useful in applications [1]. Various families of orthogonal polynomials satisfy various differential equations. These equations have a polynomial and non-polynomial solutions. What use are the latter?</p>
<p>If the differential equation modeled something physical, then the second solution would be necessary to have a complete basis of solutions. But if the differential equation is only instrumental in studying the orthogonal polynomials, what use is a non-polynomial solution?</p>
<p>These non-polynomial solutions turn out to be useful. <strong>Just as &#8220;junk&#8221; DNA turned out not to be junk, these &#8220;junk&#8221; solutions are important</strong>. Junk DNA doesn&#8217;t directly code for proteins, but it regulates DNA that does code for proteins and serves other purposes. Similarly, these non-polynomial solutions carry information related to the polynomial solutions.</p>
<p>For example, orthogonal polynomials are used to construct numerical integration methods, such as Gaussian quadrature, and the associated non-polynomial solutions describe the error in these integration methods. Incidentally, Gaussian quadrature is based on Legendre polynomials, mentioned in the <a href="https://www.johndcook.com/blog/2026/08/26/ultraspherical/">previous post</a>. For every family of orthogonal polynomials there is a corresponding integration method. See <a href="https://www.johndcook.com/OrthogonalPolynomials.pdf">these notes</a>.</p>
<p>Another tie-in to recent posts is that these non-polynomial solutions are the minimal solution to the polynomial family&#8217;s <a href="https://www.johndcook.com/blog/2026/08/24/three-term-recurrences/">three-term recurrence</a>, the solution that takes <a href="https://www.johndcook.com/blog/2026/08/24/numerical-instability-recurrece/">extra care</a> to compute numerically.</p>
<p>This post has been very high-level, alluding to ideas without going into details. I&#8217;d like to write future posts that go into more depth regarding the ideas introduced here.</p>
<p>&nbsp;</p>
<p>[1] &#8220;Real analysts cannot do without Fourier, complex analysts cannot do without Laurent, and numerical analysts cannot do without Chebyshev [polynomials].&#8221; &#8212; Lloyd N. Trefethen&#8221;</p>The post <a href="https://www.johndcook.com/blog/2026/08/26/junk-solutions/">Junk solutions</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ultraspherical</title>
		<link>https://www.johndcook.com/blog/2026/08/26/ultraspherical/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Wed, 26 Aug 2026 10:51:32 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Differential equations]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247742</guid>

					<description><![CDATA[<p>When I hear the term ultraspherical I think of something extremely spherical. For example, a baseball is spherical, but a billiard ball is more spherical. Maybe a highly polished billiard ball is ultraspherical. Using this line of thought, the term ultraspherical polynomial is inexplicable. This is an example of the arcane terminology I wrote about recently. In [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/26/ultraspherical/">Ultraspherical</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>When I hear the term <em>ultraspherical</em> I think of something extremely spherical. For example, a baseball is spherical, but a billiard ball is more spherical. Maybe a highly polished billiard ball is ultraspherical.</p>
<p>Using this line of thought, the term <strong>ultraspherical polynomial</strong> is inexplicable. This is an example of the <a href="https://www.johndcook.com/blog/2026/08/23/arcane-terminology/">arcane terminology</a> I wrote about recently. In this post I&#8217;ll explain what it conveys.</p>
<p>A spherical polynomial is a polynomial that naturally falls out of solving Laplace&#8217;s equation in spherical coordinates, using separation of variables. Legendre polynomials are spherical polynomials.</p>
<p><strong>Gegenbauer polynomials</strong> are so called because a man named Gegenbauer studied them, just as Legendre polynomials take their name from Legendre. Gegenbauer polynomials are also called ultraspherical polynomials. Why is that?</p>
<p>There are two possible reasons. I&#8217;m not sure which is the historical reason, but both are plausible and are useful mnemonics.</p>
<p>Ultraspherical polynomials are not extremely spherical, they&#8217;re <em>beyond</em> spherical in some sense. More modern terminology uses the hyper- prefix rather than ultra-, which helps a bit.</p>
<p>Ultraspherical polynomials are beyond spherical in two ways. Gegenbauer polynomials are a generalization of Legendre polynomials, so they&#8217;re beyond Legendre polynomials in this sense.</p>
<p>More importantly, Gegenbauer polynomials fall out of solving Laplace&#8217;s equation on a hypersphere, i.e. a sphere in ℝ<sup><em>n</em></sup> for <em>n</em> &gt; 3, just as Legendre polynomials fall out of the case <em>n</em> = 3. It makes sense to call these polynomials <strong>hyperspherical</strong> because they fall out of solving an equation on a hypersphere. Unfortunately the classical term is <em>ultraspherical</em> rather than <em>hyperspherical</em>.</p>
<p>I think, but I&#8217;m not sure, that at one time higher dimensional spheres were called hyperspheres, but the the higher dimensional analog of spherical coordinates was called ultraspherical coordinates. If so, it would be understandable that the adjective modifying <em>coordinates</em> would be applied to the polynomials that result from solving equations in these coordinates.</p>The post <a href="https://www.johndcook.com/blog/2026/08/26/ultraspherical/">Ultraspherical</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Numerical (in)stability of recurrence relations</title>
		<link>https://www.johndcook.com/blog/2026/08/24/numerical-instability-recurrece/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Tue, 25 Aug 2026 01:47:47 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247737</guid>

					<description><![CDATA[<p>The previous post gave several examples of three-term recurrence relations for special functions. These relations can be computationally useful, but they have to be applied carefully. Several years ago I wrote a post on stable and unstable recurrences. In that post I show that the stability of the recurrence relation for Bessel functions produces depends [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/24/numerical-instability-recurrece/">Numerical (in)stability of recurrence relations</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>The <a href="https://www.johndcook.com/blog/2026/08/24/three-term-recurrences/">previous post</a> gave several examples of three-term recurrence relations for special functions. These relations can be computationally useful, but they have to be applied carefully.</p>
<p>Several years ago I wrote a post on <a href="https://www.johndcook.com/blog/2020/01/17/stable-recurrence-relations/">stable and unstable recurrences</a>. In that post I show that the stability of the recurrence relation for Bessel functions produces depends on which kind of Bessel function and which direction the recurrence is applied.</p>
<p>In the forward direction, computing higher order values from lower order values, works well for Bessel functions of the second kind <em>Y</em><sub><em>n</em></sub> but not for Bessel functions of the first kind <em>J</em><sub><em>n</em></sub>. In the reverse direction, the recurrence is stable for <em>J</em><sub><em>n</em></sub> but not for <em>Y</em><sub><em>n</em></sub>.</p>
<p>I didn&#8217;t explain in that post why this is. In this post I will.</p>
<p>Second order linear difference equations have two independent solutions, just like second order linear differential equations. For both kinds of equations, all solutions are linear combinations of the two solutions. Suppose one solution grows with <em>n</em> and the other decays. You may want to compute the decaying solution, but in doing so you might pick up a small component of the growing solution due to rounding error. <a href="https://www.johndcook.com/blog/2013/11/12/sensitive-dependence-on-initial-conditions/">This post</a> illustrates this phenomena for differential equations, and <a href="https://www.johndcook.com/blog/2020/01/17/stable-recurrence-relations/">this post</a> illustrates it for difference equations.</p>
<p>When you look at a plot of Bessel functions in a text book, you&#8217;ll probably see a few plots of <em>J</em><sub><em>n</em></sub>(<em>x</em>) and<em>Y</em><sub><em>n</em></sub>(<em>x</em>) for a few small values of <em>n</em>. The functions seem to behave roughly the same way, like sine and cosine. And that&#8217;s true, <strong>as functions of <em>x</em></strong>.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/bessel_vary_x.png" width="480" height="360" /></p>
<p>But it&#8217;s not true for <em>J</em><sub><em>n</em></sub>(<em>x</em>) and<em>Y</em><sub><em>n</em></sub>(<em>x</em>) as functions of <em>n</em> for fixed <em>x</em>. As <em>n</em> increases, <em>J</em><sub><em>n</em></sub>(<em>x</em>) decays to zero and <em>Y</em><sub><em>n</em></sub>(<em>x</em>) goes off to −∞.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/bessel_vary_nu.png" width="480" height="360" /></p>
<p>That&#8217;s the source of numerical instability. And there will be similar instability problems for other recurrences where the ratios of the two independent solutions goes to zero or infinity as a function of <em>n</em>.</p>
<p>There are techniques for computing the solution that does not diverge, the so-called minimal solution, such as Miller&#8217;s algorithm mentioned <a href="https://www.johndcook.com/blog/2020/01/17/stable-recurrence-relations/">here</a>.</p>
<p>&nbsp;</p>The post <a href="https://www.johndcook.com/blog/2026/08/24/numerical-instability-recurrece/">Numerical (in)stability of recurrence relations</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Three-term recurrences</title>
		<link>https://www.johndcook.com/blog/2026/08/24/three-term-recurrences/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Mon, 24 Aug 2026 14:14:55 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247726</guid>

					<description><![CDATA[<p>There many examples of families of functions where each function can be computed as a linear combination of the two previous terms where a and b are functions of x and possibly n. This is called a three-term recurrence formula. It&#8217;s amazing how often you can run into three-term recurrence formulas. There are theorems that give conditions for [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/24/three-term-recurrences/">Three-term recurrences</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>There many examples of families of functions where each function can be computed as a linear combination of the two previous terms</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence.svg" alt="f_{n+1}(x) = a(x) f_n(x) + b(x) f_{n-1}(x)" width="276" height="18" /></p>
<p>where <em>a</em> and <em>b</em> are functions of <em>x</em> and possibly <em>n</em>. This is called a three-term recurrence formula.</p>
<p>It&#8217;s amazing how often you can run into three-term recurrence formulas. There are theorems that give conditions for such recurrences to hold, but I haven&#8217;t reached the bottom of that rabbit hole [1].</p>
<p>For this post I just want to give examples.</p>
<p>NB: before using any of the recurrences below, see the <a href="https://www.johndcook.com/blog/2026/08/24/numerical-instability-recurrece/">next post</a> for a numerical pitfall to avoid.</p>
<p><strong>Bessel functions</strong> of the first and second kind:</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence_bessel.svg" alt="\begin{align*} J_{\nu+1}(x) &amp;= \frac{2\nu}{x}\,J_\nu(x) - J_{\nu-1}(x) \\ Y_{\nu+1}(x) &amp;= \frac{2\nu}{x}\,Y_\nu(x) - Y_{\nu-1}(x) \end{align*}" width="237" height="88" /></p>
<p><strong>Modified Bessel functions</strong> of the first and second kind:</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence_modified_bessel.svg" alt="\begin{align*} I_{\nu+1}(x) &amp;= I_{\nu-1}(x) - \frac{2\nu}{x}\,I_\nu(x) \\ K_{\nu+1}(x) &amp;= K_{\nu-1}(x) + \frac{2\nu}{x}\,K_\nu(x) \end{align*}" width="245" height="88" /></p>
<p><strong>Chebyshev polynomials</strong> of the first and second kind:</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence_chebyshev.svg" alt="\begin{align*} T_{n+1}(x) &amp;= 2x\,T_n(x) - T_{n-1}(x) \\ U_{n+1}(x) &amp;= 2x\,U_n(x) - U_{n-1}(x) \end{align*}" width="244" height="47" /></p>
<p><strong>Hermite polynomials</strong> (physicists&#8217; convention):</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence_hermite.svg" alt="H_{n+1}(x) = 2x\,H_n(x) - 2n\,H_{n-1}(x)" width="271" height="18" /></p>
<p><strong>Legendre polynomials</strong>:</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/recurrence_legendre.svg" alt="P_{n+1}(x) = \frac{2n+1}{n+1}\,x\,P_n(x) - \frac{n}{n+1}\,P_{n-1}(x)" width="335" height="40" /></p>
<p>[1] See Bochner&#8217;s theorem for orthogonal polynomials, the Nikiforov–Uvarov method, and Infeld-Hull factorization.</p>The post <a href="https://www.johndcook.com/blog/2026/08/24/three-term-recurrences/">Three-term recurrences</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The von Mises-Fisher distribution</title>
		<link>https://www.johndcook.com/blog/2026/08/24/von-mises-fisher/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Mon, 24 Aug 2026 14:14:25 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Probability]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247719</guid>

					<description><![CDATA[<p>Probability density function must integrate to 1, and so if you know a density function up to a constant, the constant is determined. When you&#8217;re looking at a probability density f(x) for the first time, it helps to ignore the normalizing constant. Concentrate on the part of the function involving x and know that the normalizing [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/24/von-mises-fisher/">The von Mises-Fisher distribution</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Probability density function must integrate to 1, and so if you know a density function up to a constant, the constant is determined.</p>
<p>When you&#8217;re looking at a probability density <em>f</em>(<em>x</em>) for the first time, it helps to ignore the normalizing constant. Concentrate on the part of the function involving <em>x</em> and know that the normalizing constant is whatever it has to be. For example, about half of the ink that it takes to write down a beta or chi-squared density is devoted to the normalization constant; the rest of the expression is easier to understand.</p>
<p>This post will do the opposite of the advice above and focus on normalization constants because this ties into the <a href="https://www.johndcook.com/blog/2026/08/23/modified-bessel-function/">previous post</a> on modified Bessel functions.</p>
<p>The <strong>von Mises</strong> probability distribution on a circle has two parameters, μ and κ, and its density function is</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/vonmises.svg" alt="f(x \mid \mu, \kappa) = \frac{\exp(\kappa \cos(x - \mu))}{2\pi I_0(\kappa)}" width="250" height="45" /></p>
<p>The normalizing constant is 2π <em>I</em><sub>0</sub>(κ). The factor of 2π is unsurprising for anything defined on a circle. The more interesting part is <em>I</em><sub>0</sub>, the modified Bessel function of order 0.</p>
<p>The <strong>von Mises-Fisher</strong> distribution is the generalization of the von Mises distribution to a sphere in <em>p</em> dimensions. The density function is</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/vonmises_fisher.svg" alt="f(\mathbf{x} \mid \boldsymbol{\mu}, \kappa) = C_{p}(\kappa) \exp \left( {\kappa \boldsymbol{\mu}^\mathsf{T} \mathbf{x} } \right)" width="247" height="36" /></p>
<p>where the normalization constant <em>C</em><sub><em>p</em></sub>(κ) is</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/vonmises_fisher_norm.svg" alt="C_{p}(\kappa)=\frac {\kappa^{p/2-1}} {(2\pi)^{p/2}I_{p/2-1}(\kappa)}" width="206" height="52" /></p>
<p>where <em>I</em><sub><em>p</em>/2 − 1</sub> is the modified Bessel function of order <em>p</em>/2 − 1. The values of <strong>x</strong> and <strong>μ</strong> are in bold face because they are now vectors, points on the unit sphere.</p>
<p>When <em>p</em> = 2, we have the &#8220;sphere&#8221; in two dimensions, i.e. the circle, and the von Mises-Fisher distribution reduces to the von Mises distribution. But where did the cosine go? The inner product of <strong>x</strong> and <strong>μ</strong> is the cosine of the angle between the two vectors.</p>
<p>When <em>p</em> = 3, obviously an important special case, the von Mises-Fisher distribution is known as the <strong>Fisher</strong> distribution. In that case the normalizing constant <em>C</em><sub>3</sub>(κ) can be written without using modified Bessel functions because when ν = ½ + <em>n</em> for an integer <em>n</em>, <em>I</em><sub>ν</sub>(<em>x</em>) is an elementary function.</p>The post <a href="https://www.johndcook.com/blog/2026/08/24/von-mises-fisher/">The von Mises-Fisher distribution</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What exactly is modified about a modified Bessel function?</title>
		<link>https://www.johndcook.com/blog/2026/08/23/modified-bessel-function/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sun, 23 Aug 2026 18:40:57 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Differential equations]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247707</guid>

					<description><![CDATA[<p>Special functions often have arcane names that not very helpful without some context. The previous post goes into some reasons for this. This post will expand on a point at the end of the post about &#8220;modified&#8221; functions. Things are given their names for reasons. Discovering those reasons may help you understand their motivation and [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/23/modified-bessel-function/">What exactly is modified about a modified Bessel function?</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Special functions often have arcane names that not very helpful without some context. The <a href="https://www.johndcook.com/blog/2026/08/23/arcane-terminology/">previous post</a> goes into some reasons for this. This post will expand on a point at the end of the post about &#8220;modified&#8221; functions.</p>
<p>Things are given their names for reasons. Discovering those reasons may help you understand their motivation and use.</p>
<h2>Pure math perspective</h2>
<p>For each integer <em>n</em>, the modified Bessel function <em>I<sub>n</sub></em> is essentially the Bessel function <em>J<sub>n</sub></em> evaluated along the imaginary axis. Specifically,</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/modified_bessel2.svg" alt="I_n(x) = i^{-n} J_n(ix)" width="135" height="18" /></p>
<p>From a certain shallow perspective, that&#8217;s the end of the story: modified Bessel functions are modified in the sense that the argument is multiplied by <em>i</em>. And there&#8217;s a fiddly constant term up front for no apparent reason.</p>
<p>But of course that&#8217;s not the end of the story or else this wouldn&#8217;t be worth an entire post.</p>
<p>The equation above is analogous to the relationships between circular and hyperbolic functions</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/modified_bessel3.svg" alt="\begin{align*} \sin(ix) &amp;= i \sinh(x) \\ \cos(ix) &amp;= \phantom{i} \cosh(x) \\ \tan(ix) &amp;= \phantom{i} \tanh(x) \end{align*}" width="154" height="76" /></p>
<p>These relationships are interesting because the circular and hyperbolic functions are independently meaningful. If you view these equations merely as definitions you lose their significance. Circular and hyperbolic functions were widely used before Euler discovered the connection between them.</p>
<p>Similarly, there&#8217;s a reason the modified Bessel functions were given a name their own. If you were led to Bessel functions and modified Bessel functions separately by different applications, you would regard the equation</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/modified_bessel2.svg" alt="I_n(x) = i^{-n} J_n(ix)" width="135" height="18" /></p>
<p>as a <strong>discovery</strong> rather than just a definition. The following section explains why someone would be interested in modified Bessel functions.</p>
<p>Before we move on, I&#8217;d like to explain the reason for the term <em>i</em><sup>−<em>n</em></sup> term. In general</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/modified_bessel4.svg" alt="I_\nu(x) = \exp(\nu\pi i/2) J_n(ix)" width="202" height="18" /></p>
<p>for all real ν. The reason for the exp(νπ<em>i</em>/2) term is that it makes <em>I</em><sub>ν</sub>(<em>x</em>) real for all real <em>x</em>.</p>
<h2>Applied math perspective</h2>
<p>Bessel functions often arise from solving problems with <strong>radial symmetry</strong>. Solving the <strong>wave equation</strong> in cylindrical coordinates using separation of variables leads to Bessel&#8217;s differential equation</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/bessel_equation.svg" alt="x^2 y'' + x y' + (x^2 - \nu^2) y = 0" width="212" height="20" /></p>
<p>and its solutions <em>J<sub>n</sub></em> and <em>Y<sub>n</sub></em>, Bessel functions of the first and second kind.</p>
<p>Solving the <strong>heat equation</strong> in cylindrical coordinates with separation of variables leads to the <em>modified</em> Bessel equation</p>
<p><img loading="lazy" decoding="async" class="aligncenter" style="background-color: white;" src="https://www.johndcook.com/modified_bessel5.svg" alt="x^2 y^{\prime \prime} + x y^{\prime} - (x^2 + \nu^2) y = 0" width="225" height="22" /></p>
<p>and its solutions <em>I<sub>n</sub></em> and <em>K<sub>n</sub></em>, the <em>modified</em> Bessel functions of the first and second kind.</p>
<p>This is the reason behind the complex analysis perspective above: the change of variables sending <em>x</em> to <em>ix</em> changes the sign of the <em>x</em>² term in Bessel&#8217;s equation.</p>
<p>Bessel functions describe radially symmetric <strong>oscillations</strong>, such as the vibrations of a drum head. Modified Bessel functions describe radially symmetric <strong>exponential</strong> growth or decay [1], such as in the heat in a cylinder.</p>
<h2>Other modified functions</h2>
<p><strong>Struve functions</strong> are closely related to Bessel functions. The (modified) Struve functions also satisfy Bessel&#8217;s (modified) differential equation, but with a non-zero right hand side. The modified Struve functions are proportional to the unmodified Struve functions evaluated along the imaginary axis, with a proportionality constant that makes the modified Struve functions real for real arguments.</p>
<p>There&#8217;s a similar relationship between the <strong>Mathieu functions</strong> and modified Mathieu functions. The general pattern is that &#8220;modified&#8221; in the context of special functions means &#8220;evaluated at <em>ix</em> and multiplied by a constant to make the function real for real arguments.&#8221;</p>
<p>&nbsp;</p>
<p>[1] The functions <em>I<sub>n</sub></em> grow exponentially and the functions <em>K<sub>n</sub></em> decay exponentially. For this reason, <a href="https://www.johndcook.com/blog/2017/02/26/function-on-cover-of-abramowitz-stegun/">A&amp;S</a> didn&#8217;t tabulate <em>I<sub>n</sub></em> and <em>K<sub>n</sub></em> per se. Instead it tabulated <em>e</em><sup>−<em>x</em></sup><em>I<sub>n</sub></em> and <em>e</em><sup><em>x</em></sup><em>K<sub>n</sub></em> because these functions varied less over their range.</p>The post <a href="https://www.johndcook.com/blog/2026/08/23/modified-bessel-function/">What exactly is modified about a modified Bessel function?</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Why special function terminology is arcane</title>
		<link>https://www.johndcook.com/blog/2026/08/23/arcane-terminology/</link>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sun, 23 Aug 2026 17:56:03 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Special functions]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247705</guid>

					<description><![CDATA[<p>Special functions are special because they&#8217;re useful. They can also be shrouded in arcane terminology. These two facts are related. The more widely useful a function is, the more likely it is that the function will be discovered independently multiple times. Independent discoveries lead to varying definitions and notations. For example, there are two widely [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/23/arcane-terminology/">Why special function terminology is arcane</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Special functions are special because they&#8217;re useful. They can also be shrouded in arcane terminology. These two facts are related.</p>
<p>The more widely useful a function is, the more likely it is that the function will be discovered independently multiple times. Independent discoveries lead to varying definitions and notations. For example, there are two widely used definitions of Hermite polynomials, one used in <a href="https://www.johndcook.com/blog/2017/12/20/hermite-polynomials-expected-values-and-integration/">probability</a> and another used in physics, that only differ by a scaling factor. This also explains why there are so many variations on the definitions of the <a href="https://www.johndcook.com/blog/2022/03/20/reverse-engineering-fourier-conventions/">Fourier transform</a> and <a href="https://www.johndcook.com/blog/2023/08/12/spherical-coordinate-rosetta-stone/">spherical coordinates</a>.</p>
<p>Special functions were discovered and applied before they were studied systematically. As with most mathematics, practice preceded theory. In hindsight, some names and conventions were less than ideal, at least from the perspective of someone seeking to organize a theory.</p>
<p>Functions can have arcane names for several reasons, one being that their usefulness became apparent long ago. If your instinct is that things with strange names are no longer important, your instinct might be backward. The strange name may be an indication that something is so important that its usefulness became apparent long ago.</p>
<p>Sometimes special functions have bland, uninformative names because the names stuck before anybody could think of something better. Bob looks into an interesting family of functions [1], then later he finds another interesting family of functions. These become known as &#8220;Bob&#8217;s functions of the first kind&#8221; and &#8220;Bob&#8217;s functions of the second kind.&#8221; These names are quite understandable at the time, though in the future people will want to know what distinguishes the functions, other than the fact that Bob discovered them, and what the groupings have in common other than the order in which Bob found them.</p>
<p>I started this post intending to discuss modified Bessel functions and explain what exactly is modified about them, but my preface became its own post. &#8220;Modified&#8221; is an example of the bland terminology mentioned above. There are Bessel functions and modified Bessel functions. Without more context, the &#8220;modified&#8221; term isn&#8217;t very informative. But it does provide a clue that there&#8217;s some kind of close relationship between the modified and unmodified functions. That&#8217;ll be the topic of my next post.</p>
<p>&nbsp;</p>
<p>[1] Math education doesn&#8217;t place much emphasis on history and motivation. You may have to do some digging to find out why Bob was interested in his functions. What else was Bob known for? Maybe they&#8217;re related.</p>The post <a href="https://www.johndcook.com/blog/2026/08/23/arcane-terminology/">Why special function terminology is arcane</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The difference orbit inclination makes</title>
		<link>https://www.johndcook.com/blog/2026/08/22/inclination/</link>
					<comments>https://www.johndcook.com/blog/2026/08/22/inclination/#comments</comments>
		
		<dc:creator><![CDATA[John]]></dc:creator>
		<pubDate>Sun, 23 Aug 2026 00:01:10 +0000</pubDate>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Orbital mechanics]]></category>
		<guid isPermaLink="false">https://www.johndcook.com/blog/?p=247702</guid>

					<description><![CDATA[<p>Suppose you wanted to find the distance between Earth and Mars over time. To first approximation, both planets orbit the sun in elliptic orbits in the same plane. If you wanted to be more accurate, you&#8217;d need to take into account the fact that the orbit of Mars is tilted about 1.85° relative to the [&#8230;]</p>
The post <a href="https://www.johndcook.com/blog/2026/08/22/inclination/">The difference orbit inclination makes</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></description>
										<content:encoded><![CDATA[<p>Suppose you wanted to find the distance between Earth and Mars over time. To first approximation, both planets orbit the sun in elliptic orbits in the same plane.</p>
<p>If you wanted to be more accurate, you&#8217;d need to take into account the fact that the orbit of Mars is tilted about 1.85° relative to the Earth&#8217;s orbit. How much difference does that make?</p>
<p>To simplify things, let&#8217;s assume the Earth orbits the sun in a circle of radius 1 and Mars orbits the sun in a circle of radius 1.5. The distance between Earth and Mars over time would be basically sinusoidal.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/mars_distance0.png" width="480" height="360" /></p>
<p>How much does inclination contribute to this distance? In other words, what is the difference between the distance accounting for the inclination of Mars&#8217; orbit and the distance if we assume the two orbits are in the same plane?</p>
<p>This plot gives the answer.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-medium" src="https://www.johndcook.com/mars_distance1.png" width="480" height="360" /></p>
<p>The effect is not large, about three orders of magnitude smaller than the main effect, but it&#8217;s interesting how erratic it is.</p>
<p>The plots were made with the following code.</p>
<pre>from numpy import *

R = 1.5
T = R**1.5 # Kepler's third law

def f(t, theta):
    return sqrt(
        (cos(t) - R*cos(t/T)*cos(theta))**2 +
        (sin(t) - R*sin(t/T))**2 +
        (R*sin(theta)*cos(t/T))**2
    )
</pre>
<p>The first plot graphs <em>f</em>(<em>t</em>, θ) and the second graphs <em>f</em>(<em>t</em>, θ) − <em>f</em>(<em>t</em>, 0).</p>The post <a href="https://www.johndcook.com/blog/2026/08/22/inclination/">The difference orbit inclination makes</a> first appeared on <a href="https://www.johndcook.com/blog">John D. Cook</a>.]]></content:encoded>
					
					<wfw:commentRss>https://www.johndcook.com/blog/2026/08/22/inclination/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
