Latest Posts (20 found)
Unsung Today

Max one weird thing

If you want to record the screen from your iPhone on your Mac, open the QuickTime Player app but ignore New Screen Recording, and click on New Movie Recording instead. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/max-one-weird-thing/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/max-one-weird-thing/1.1600w.avif" type="image/avif"> This instruction is a fever dream of three weird things in sequence: It’s interesting to me to think how we got here: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/max-one-weird-thing/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/max-one-weird-thing/2.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/max-one-weird-thing/3.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/max-one-weird-thing/3.1600w.avif" type="image/avif"> Long ago, the Player was the only free, consumer-facing part of QuickTime, so it needed special branding. You could purchase QuickTime Pro – you would even get aggressive ad banners for it inside Mac OS! – and its encoding and saving capabilities would then be sprinkled across the entire system. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/max-one-weird-thing/4.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/max-one-weird-thing/4.1600w.avif" type="image/avif"> “New Movie Recording” originally offered recording from external video cameras (like iSight , another cute name). “New Screen Recording” was added later, for recording from internal screens. My guess is that technically, architecturally, or both, it was easier to treat external screens (like iPhone or Apple TV) as external video cameras since the UI and affordances matched them more closely. So that’s why screen recording from external devices ended up under “New Movie Recording.” As a UX historian, this is fun and fascinating! I love tracing back that kind of stuff and learning how certain strange things came to be. As a user… not so much. “If you want to record the screen from your iPhone on your Mac, open the QuickTime Player app but ignore New Screen Recording, and click on New Movie Recording instead.” This feels thrice arbitrary, closer to a magical incantation than a computer command, requiring you to hold a bunch of counterintuitive things in your head, or look them up every time. “Wait, what was the strange name?“ “Yeah, it’s called a player, but that’s ok.” “Hmm, I remember something about not choosing the obvious command.“ I have this internal rule that a flow or a space in the UI should have at most one weird thing. I can’t prove it to you mathematically, and I would be the first to find exceptions to my own rule. But one weird thing makes me nervous, and two or more weird things in concert raise the hair at the back of my neck. Two weird things is when the “launch blocking” bulb lights up in my head. Work needs to happen to bring the weirdness count back to 1 or 0. This is one example of what I dragged Apple earlier for : it’s not just speed that matters. It’s noticing this kind of complexity, places where an easy way was chosen, design debt accumulated, and things got simply too weird. Apple allowed three weird things to accumulate here. (By the way, delightful weird doesn’t count! But it’s hard for me to imagine anyone defending these three things above as delightful or positive in any way.) “If you want to record the screen from your iPhone on your Mac, open the QuickTime Player app but ignore New Screen Recording, and click on New Movie Recording instead.” “If you want to record the screen from your iPhone on your Mac, open the Recorder app and click on New Screen Recording.” It’s not trivial to get to this or something similar, but it’s also not really hard . You can get rid of weird things, but you need to want it. #apple #change management #complexity What on earth is “QuickTime”? I am recording with a player ? Why can’t I choose the option that describes exactly what I want to do? QuickTime is a 1990s brand, an offshoot of QuickDraw. Instead of QuickAnimate or QuickPlay, Apple called it QuickTime because it felt cute: time is what separates static images from video. The branding was much more prominent in the 1990s and 2000s, but mostly fell out of use – searching for “quicktime” in system settings today, for example, yields zero results. Long ago, the Player was the only free, consumer-facing part of QuickTime, so it needed special branding. You could purchase QuickTime Pro – you would even get aggressive ad banners for it inside Mac OS! – and its encoding and saving capabilities would then be sprinkled across the entire system. “New Movie Recording” originally offered recording from external video cameras (like iSight , another cute name). “New Screen Recording” was added later, for recording from internal screens. My guess is that technically, architecturally, or both, it was easier to treat external screens (like iPhone or Apple TV) as external video cameras since the UI and affordances matched them more closely. So that’s why screen recording from external devices ended up under “New Movie Recording.”

0 views

IBM Misses, IBM’s Mainframe Moat, IBM’s Many AI Problems

IBM announced preliminary results that spooked the software market generally; this is a story, however, specifically about IBM and its mainframe franchise.

0 views

Dinosaur Discovery Returns

What’s going on, Internet? Last year we discovered the dinosaurs at Auckland Zoo , and this year we went back for round two. They’ve added some new dinosaurs to the track this year, so it was well worth the revisit. We made the trip with my brother and his kids again, and this year my parents were up for the week so it was a great family night out. The kids are all a year older, we stayed out later and they had a great time. My youngest who is two years old now was a bit scared, but was able to put on a brave face walking around with daddy. I expect many more visits to the dinosaurs during the day as we visit the zoo during the upcoming weekends. I might never ever get to the NZ birds section (I have been trying with each zoo visit, lol). Enjoy the photos. ← Previous 1 / 18 Next → Close ← Previous 2 / 18 Next → Close ← Previous 3 / 18 Next → Close ← Previous 4 / 18 Next → Close ← Previous 5 / 18 Next → Close ← Previous 6 / 18 Next → Close ← Previous 7 / 18 Next → Close ← Previous 8 / 18 Next → Close ← Previous 9 / 18 Next → Close ← Previous 10 / 18 Next → Close ← Previous 11 / 18 Next → Close ← Previous 12 / 18 Next → Close ← Previous 13 / 18 Next → Close ← Previous 14 / 18 Next → Close ← Previous 15 / 18 Next → Close ← Previous 16 / 18 Next → Close ← Previous 17 / 18 Next → Close ← Previous 18 / 18 Next → Hey, thanks for reading this post in your feed reader! Want to chat? Reply by email or add me on XMPP , or send a webmention . Check out the posts archive on the website.

0 views

Notes on the Fourier Transform

The Fourier series is a great tool for analyzing periodic functions. But what about functions that don’t repeat? We’ve seen that we can compute Fourier series for a non-periodic function defined on a finite interval, as long as we don’t care about its behavior beyond that interval. Let’s extend this idea to functions that never repeat; that is, non-periodic functions defined on the interval (-\infty,\infty) . To motivate the subject ahead, let’s look back at the example used in the earlier post about Fourier series : With an odd extension into [-2,0] . In that post, to make the Fourier series work, we assumed t(x) keeps repeating with a period 2L=4 on the entire x axis. Here, let’s face the reality that it does not - in fact - repeat, and observe how our Fourier series work out. Recall that the Fourier series approximating t(x) are the sine series (since it’s an odd function): The following visualization is interactive. By default, it shows t(x) (with its odd extension) and no Fourier series approximation. We’ll proceed by a series of steps and observe the outcome: Step 1 : set to some non-zero number; already at 3, the approximation is very good. The frequency spacing is \frac{\pi}{L} (this is the coefficient of x in the sines). Note that the Fourier series repeats every 2L , as expected. Step 2 : increase L to 6. This means our series are constructed assuming t(x) has a period of 12, not 4. Note how the Fourier series look now - they repeat every 12, and they don’t match t(x) as well as before. We can increase to a higher number to make the match better. As L grows, the spacing between adjacent frequencies decreases. Step 3 : increase L to 10. We no longer see the repetitions, so feel free to increase the values of x min and x max until you do. Note again that we need to add more and more coefficients to match t(x) better with this larger L , and the spacing adjacent frequencies grows smaller. Increasing L means our function repeats at larger and larger intervals. The logical conclusion of this progression is to ask - what happens if the function never repeats, meaning L\rightarrow\infty ? While not mathematically rigorous, the visual experiment here lets us make some conjectures: we’ll likely need an infinite number of coefficients for a good approximation, and moreover, the spacing between these coefficients will tend to zero. In other words, instead of a discrete set of coefficients, we’ll end up with a continuous line, or function . The function produced by this process is the Fourier transform of t(x) , and the next section shows its mathematical derivation. In these notes, we’ll be using the complex exponential formulation of Fourier series: We’re interested in a non-periodic defined on the interval (-\infty,\infty) . So we’ll be exploring the above equations for L\rightarrow\infty . First, let’s make a slight change of notation. Instead of writing formulae in terms of the period ( 2L ), we’ll be using the n-th harmonic angular frequency w_n : So we can slightly rewrite our series as: Using \Delta w as the difference between two consecutive frequencies: Using this notation, C_n is expressed as: So far there are no new insights here, just some new notation. Now we’re going to use it to facilitate the next step. Since L\rightarrow \infty , then \Delta w\rightarrow 0 . Let’s calculate the limit of the Fourier series representation of when \Delta w\rightarrow 0 : And substitute the latest C_n into this equation, changing its dummy integration variable from x to t to avoid confusion [1] Reordering slightly, and also replacing n\Delta w by w_n in the complex exponents: Looking at the limit with the sum carefully, this is a Riemann sum (see Appendix A)! w_n is the "sampled" version of , and \Delta w\rightarrow 0 . We can therefore replace it by an integral, changing w_n to and \Delta w to dw [2] : The inner integral is called the Fourier transform of and denoted [3] : And the full equation for is then the inverse Fourier transform: Let’s take our favorite odd triangular pulse example and calculate its Fourier transform. The function’s mathematical definition and plot are shown earlier in this post. Note that we’re not extending this function periodically - it’s zero beyond the range [-2,2] ; this is exactly why we need the Fourier transform here - as we’ve seen, Fourier series won’t do because the function they reconstruct eventually starts repeating. We’re looking to find: To calculate the integral, let’s decompose the complex exponent using Euler’s formula: Since our t(x) is odd, the first integral is zero . Also t(x)sin(wx) is even, so we can write: We’ve already calculated a very similar integral in the post on Fourier series , so let’s just skip to the result: The only remaining difficulty is its value at 0, which seems undefined at first (division by zero). However, note that as w\rightarrow 0 , the numerator also tends to 0, so we can use L’Hopital’s rule (twice!) to find that: This function is complex-valued; in fact, it’s purely imaginary. How do we visualize it? A common way to visualize complex-valued functions is by plotting their magnitude and phase separately. The magnitude of \hat{t}(w) is: Since \hat{t}(w) is purely imaginary, there are only two options for the phase: When the numerator is positive, we get a negative imaginary number with phase -\pi/2 , and when the numerator is negative, we get a positive imaginary number with phase \pi/2 . Finally, when \hat{t}(w)=0 (which happens at w=0 , by our earlier analysis, but also whenever is a whole multiple of \pi ), the phase is undefined. Here’s the magnitude and phase of \hat{t}(w) plotted against : It is common to talk about \hat{t}(w) as the frequency domain representation of t(x) . When the functions we’re working with have time as their domain (e.g. the x in t(x) represents time), which is often the case in the study of signals and systems, the Fourier transform can be seen as computing the frequency domain representation of the function. Here’s the Fourier transform formula again: It takes - the time domain representation of a function, and converts it to \hat{f}(w) - a frequency domain representation. For well-behaved functions, these two representations are dual - each one describes the function completely, just in a different way. To convert back from a frequency domain representation to the time domain, we use the inverse Fourier transform: While a time-domain plot ( t(x) ) shows how a signal changes over time, a frequency-domain plot ( \hat{t}(w) ) shows how the signal is distributed across all possible frequencies. Moreover, as we’ve seen, \hat{t}(w) is complex valued. Each frequency therefore has both a magnitude and a phase: the magnitude tells us how strongly that frequency contributes, while the phase tells us how that component is shifted. The frequency domain is extremely useful in signal analysis; for example, when designing filters. The Fourier transform also has a number of properties that are very useful in signal analysis and processing. But first, let’s discuss what a "well-behaved function" means for the purpose of applying Fourier transforms. The simplest existence condition for Fourier transforms is absolute integrability (also known as Lebesgue integrable): With this condition, \hat{f}(w) exists on the entire domain, is continuous and vanishes (tends to 0) as |w|\rightarrow\infty [4] . While this condition is sufficient, it’s not necessary; there are less well-behaved functions that also have Fourier transforms defined with some limitations. In these notes, we’re mostly interested in well-behaved functions that are used in real-world engineering, so we won’t discuss the other cases. Another assumption commonly made for real-world functions is that they vanish (tend to 0) as |x|\rightarrow\infty . While this is not a direct outcome of absolute integrability [5] , it’s a reasonable assumption in engineering. After all, real-world signals have finite energies. Intuitively, when we also assume is uniformly continuous , the assumption of vanishing at |x|\rightarrow\infty is a logical conclusion, because otherwise how can the total area for |f(x)| be finite? An important outcome of this discussion is that the Fourier transform is unsuitable for periodic functions. Functions that repeat at intervals are not absolute integrable . For periodic functions, we use Fourier series. The Fourier transform is a linear operator, because the integral is linear: So is the inverse Fourier transform; it’s similarly easy to show that: If we scale the domain of a function by a constant, its transform changes only slightly: Let’s do the variable substitution u=ax : This is the Fourier transform evaluated at \frac{w}{a} , so: There’s one small caveat here; when a is negative, the integral bounds should be flipped, causing a minus sign in front of the transform. So we can write: Which works for any a\ne 0 . This property is intuitive when thinking about signals: suppose a>0 , then f(ax) means the signal is compressed in the time domain by a factor a . The scaling property says that the frequency domain is expanded using the same factor; in other words, the higher frequencies become more prominent because we need sharper transitions to represent the compressed signal. Time shifting What happens to the Fourier transform if we time-shift the input signal by some constant: f(x-x_0) . By definition: Substituting u=x-x_0 , we get du=dx , so: Transform of a derivative An extremely useful property that’s often employed in the solution of partial differential equations; let’s calculate the Fourier transform of the derivative of : We’ll use integration by parts, where dv=f'(x) and u=e^{-i\cdot wx} . Therefore, v=f(x) and du=-iw\cdot e^{-i\cdot wx} : Recall the assumption made in the "Existence condition..." section about vanishing at infinities. So the first part of the equation above is zero, and we’re left with: Transform of convolution The convolution between two continuous functions and g(x) is defined as: Let’s calculate the Fourier transform of this function: This step of combining the integrals into a double integral, as well as the next step (changing the order of integration) is possible due to Fubini’s theorem and our assumption that and g(x) are Lebesgue integrable. Switch order of integration: Now, f(\xi) in the inner integral doesn’t depend on x , so we can pull it out: The inner integral is just the Fourier transform of a time-shifted g(x-\xi) , so we can write: And the remaining integral is the Fourier transform of , so: Convolution in the time domain translates to multiplication in the frequency domain! This result is so important in signal processing that it’s called the convolution theorem . Suppose we have some function and we want to know the area bounded between this function’s graph and the x axis in a certain interval [a,b] . One way to do this is to take a partition of the interval: And calculate the area under for every element of the partition. We can then approximate such sub-areas by rectangles, as follows: We’ll denote the area of each rectangle as f(x^*_i)\cdot\Delta x : There are many ways to choose which point of the interval [x_{i-1},x_i] to denote as x^*_i : left point ( x_{i-1} ), right point ( ), mid-point between the two (which is what our plot shows) or anything in between. The distinction doesn’t really matter for our purpose, as we will soon see. We can approximate the area under the curve of in the interval [a,b] with the Riemann sum , using a uniform partition: If is continuous on [a,b] , then as n\rightarrow \infty : This is known as the Riemann integral , or just the definite integral. The limit is why the exact choice of x^*_i doesn’t matter: as n\rightarrow\infty we have \Delta x\rightarrow 0 , and all points within [x_{i-1}, x_i] are equally good. The Fourier series is a great tool for analyzing periodic functions. But what about functions that don’t repeat? We’ve seen that we can compute Fourier series for a non-periodic function defined on a finite interval, as long as we don’t care about its behavior beyond that interval. Let’s extend this idea to functions that never repeat; that is, non-periodic functions defined on the interval (-\infty,\infty) . Visualizing Fourier series for non-repeating functions To motivate the subject ahead, let’s look back at the example used in the earlier post about Fourier series : \[t(x)= \begin{cases} x & 0 \leq x \leq 1 \\ 2-x & 1 < x \leq 2 \\ \end{cases}\] With an odd extension into [-2,0] . In that post, to make the Fourier series work, we assumed t(x) keeps repeating with a period 2L=4 on the entire x axis. Here, let’s face the reality that it does not - in fact - repeat, and observe how our Fourier series work out. Recall that the Fourier series approximating t(x) are the sine series (since it’s an odd function): \[t(x)=\frac{8}{\pi^2}\bigg[ sin\frac{\pi x}{2}-\frac{1}{3^2} sin\frac{3\pi x}{2}+\frac{1}{5^2}sin\frac{5\pi x}{2}-\cdots\bigg]\] The following visualization is interactive. By default, it shows t(x) (with its odd extension) and no Fourier series approximation. We’ll proceed by a series of steps and observe the outcome: n (terms in the Fourier series) L x min x max Step 1 : set to some non-zero number; already at 3, the approximation is very good. The frequency spacing is \frac{\pi}{L} (this is the coefficient of x in the sines). Note that the Fourier series repeats every 2L , as expected. Step 2 : increase L to 6. This means our series are constructed assuming t(x) has a period of 12, not 4. Note how the Fourier series look now - they repeat every 12, and they don’t match t(x) as well as before. We can increase to a higher number to make the match better. As L grows, the spacing between adjacent frequencies decreases. Step 3 : increase L to 10. We no longer see the repetitions, so feel free to increase the values of x min and x max until you do. Note again that we need to add more and more coefficients to match t(x) better with this larger L , and the spacing adjacent frequencies grows smaller. Increasing L means our function repeats at larger and larger intervals. The logical conclusion of this progression is to ask - what happens if the function never repeats, meaning L\rightarrow\infty ? While not mathematically rigorous, the visual experiment here lets us make some conjectures: we’ll likely need an infinite number of coefficients for a good approximation, and moreover, the spacing between these coefficients will tend to zero. In other words, instead of a discrete set of coefficients, we’ll end up with a continuous line, or function . The function produced by this process is the Fourier transform of t(x) , and the next section shows its mathematical derivation. Fourier series with L\rightarrow\infty leading to Fourier transform In these notes, we’ll be using the complex exponential formulation of Fourier series: \[f(x)=\sum_{n=-\infty}^{\infty}C_n\cdot e^{in\pi x/L}\] With: \[C_n=\frac{1}{2L}\int_{-L}^{L}f(x)e^{-in\pi x/L}dx\] We’re interested in a non-periodic defined on the interval (-\infty,\infty) . So we’ll be exploring the above equations for L\rightarrow\infty . First, let’s make a slight change of notation. Instead of writing formulae in terms of the period ( 2L ), we’ll be using the n-th harmonic angular frequency w_n : \[w_n=\frac{n\pi}{L}\] So we can slightly rewrite our series as: \[f(x)=\sum_{n=-\infty}^{\infty}C_n\cdot e^{i w_n x}=\sum_{n=-\infty}^{\infty}C_n\cdot e^{i\cdot n \Delta w x}\] Using \Delta w as the difference between two consecutive frequencies: \[\Delta w=w_n-w_{n-1}=\frac{n\pi}{L}-\frac{(n-1)\pi}{L}=\frac{\pi}{L}\] Using this notation, C_n is expressed as: \[C_n=\frac{\Delta w}{2\pi}\int_{-\pi/\Delta w}^{\pi/\Delta w}f(x)e^{-i\cdot n \Delta w x}dx\] So far there are no new insights here, just some new notation. Now we’re going to use it to facilitate the next step. Since L\rightarrow \infty , then \Delta w\rightarrow 0 . Let’s calculate the limit of the Fourier series representation of when \Delta w\rightarrow 0 : \[f(x)=\lim_{\Delta w\rightarrow 0}\sum_{n=-\infty}^{\infty}C_n\cdot e^{i\cdot n \Delta w x}\] And substitute the latest C_n into this equation, changing its dummy integration variable from x to t to avoid confusion [1] \[f(x)=\lim_{\Delta w\rightarrow 0}\sum_{n=-\infty}^{\infty}\left[\frac{\Delta w}{2\pi}\int_{-\pi/\Delta w}^{\pi/\Delta w}f(t)e^{-i\cdot n \Delta w t}dt\right]\cdot e^{i\cdot n \Delta w x}\] Reordering slightly, and also replacing n\Delta w by w_n in the complex exponents: \[f(x)=\frac{1}{2\pi}\lim_{\Delta w\rightarrow 0}\sum_{n=-\infty}^{\infty}\left[\int_{-\pi/\Delta w}^{\pi/\Delta w}f(t)e^{-i\cdot w_n t}dt\right]\cdot e^{i\cdot w_n x}\Delta w\] Looking at the limit with the sum carefully, this is a Riemann sum (see Appendix A)! w_n is the "sampled" version of , and \Delta w\rightarrow 0 . We can therefore replace it by an integral, changing w_n to and \Delta w to dw [2] : \[f(x)=\frac{1}{2\pi}\int_{-\infty}^{\infty}\left[\int_{-\infty}^{\infty}f(t)e^{-i\cdot wt}dt\right]\cdot e^{i\cdot w x}dw\] The inner integral is called the Fourier transform of and denoted [3] : \[\boxed{\hat{f}(w)=\mathcal{F}\left[f(x)\right]=\int_{-\infty}^{\infty}f(x)e^{-i\cdot wx}dx}\] And the full equation for is then the inverse Fourier transform: \[\boxed{f(x)=\mathcal{F}^{-1}\left[\hat{f}(w)\right]=\frac{1}{2\pi}\int_{-\infty}^{\infty}\hat{f}(w)e^{i\cdot w x}dw}\] Example calculation of Fourier transform Let’s take our favorite odd triangular pulse example and calculate its Fourier transform. The function’s mathematical definition and plot are shown earlier in this post. Note that we’re not extending this function periodically - it’s zero beyond the range [-2,2] ; this is exactly why we need the Fourier transform here - as we’ve seen, Fourier series won’t do because the function they reconstruct eventually starts repeating. We’re looking to find: \[\hat{t}(w)=\int_{-\infty}^{\infty}t(x)e^{-iwx}dx\] To calculate the integral, let’s decompose the complex exponent using Euler’s formula: \[\hat{t}(w)=\int_{-\infty}^{\infty}t(x)cos(wx)dx-i\int_{-\infty}^{\infty}t(x)sin(wx)dx\] Since our t(x) is odd, the first integral is zero . Also t(x)sin(wx) is even, so we can write: \[\hat{t}(w)=-2i\int_{0}^{\infty}t(x)sin(wx)dx\] We’ve already calculated a very similar integral in the post on Fourier series , so let’s just skip to the result: \[\hat{t}(w)=-2i\cdot\frac{2\cdot sin(w)-sin(2w)}{w^2}\] The only remaining difficulty is its value at 0, which seems undefined at first (division by zero). However, note that as w\rightarrow 0 , the numerator also tends to 0, so we can use L’Hopital’s rule (twice!) to find that: \[\lim_{w\rightarrow 0} \hat{t}(w)=0\] Therefore: \[\hat{t}(w)= \begin{cases} -2i\cdot\frac{2\cdot sin(w)-sin(2w)}{w^2} & w\neq 0 \\ 0 & w=0 \\ \end{cases}\] This function is complex-valued; in fact, it’s purely imaginary. How do we visualize it? A common way to visualize complex-valued functions is by plotting their magnitude and phase separately. The magnitude of \hat{t}(w) is: \[|\hat{t}(w)|=\sqrt{\hat{t}(w)\cdot\hat{t}(w)^*}=2\left|\frac{2\cdot sin(w)-sin(2w)}{w^2} \right|\] Since \hat{t}(w) is purely imaginary, there are only two options for the phase: When the numerator is positive, we get a negative imaginary number with phase -\pi/2 , and when the numerator is negative, we get a positive imaginary number with phase \pi/2 . Finally, when \hat{t}(w)=0 (which happens at w=0 , by our earlier analysis, but also whenever is a whole multiple of \pi ), the phase is undefined. Here’s the magnitude and phase of \hat{t}(w) plotted against : It is common to talk about \hat{t}(w) as the frequency domain representation of t(x) . The frequency domain representation of functions When the functions we’re working with have time as their domain (e.g. the x in t(x) represents time), which is often the case in the study of signals and systems, the Fourier transform can be seen as computing the frequency domain representation of the function. Here’s the Fourier transform formula again: \[\hat{f}(w)=\mathcal{F}\left[f(x)\right]=\int_{-\infty}^{\infty}f(x)e^{-i\cdot wx}dx\] It takes - the time domain representation of a function, and converts it to \hat{f}(w) - a frequency domain representation. For well-behaved functions, these two representations are dual - each one describes the function completely, just in a different way. To convert back from a frequency domain representation to the time domain, we use the inverse Fourier transform: \[\mathcal{F}^{-1}\left[\hat{f}(w)\right]=\frac{1}{2\pi}\int_{-\infty}^{\infty}\hat{f}(w)e^{i\cdot w x}dw\] While a time-domain plot ( t(x) ) shows how a signal changes over time, a frequency-domain plot ( \hat{t}(w) ) shows how the signal is distributed across all possible frequencies. Moreover, as we’ve seen, \hat{t}(w) is complex valued. Each frequency therefore has both a magnitude and a phase: the magnitude tells us how strongly that frequency contributes, while the phase tells us how that component is shifted. The frequency domain is extremely useful in signal analysis; for example, when designing filters. The Fourier transform also has a number of properties that are very useful in signal analysis and processing. But first, let’s discuss what a "well-behaved function" means for the purpose of applying Fourier transforms. Existence condition for the Fourier transform The simplest existence condition for Fourier transforms is absolute integrability (also known as Lebesgue integrable): \[\int_{-\infty}^{\infty}|f(x)|dx<\infty\] With this condition, \hat{f}(w) exists on the entire domain, is continuous and vanishes (tends to 0) as |w|\rightarrow\infty [4] . While this condition is sufficient, it’s not necessary; there are less well-behaved functions that also have Fourier transforms defined with some limitations. In these notes, we’re mostly interested in well-behaved functions that are used in real-world engineering, so we won’t discuss the other cases. Another assumption commonly made for real-world functions is that they vanish (tend to 0) as |x|\rightarrow\infty . While this is not a direct outcome of absolute integrability [5] , it’s a reasonable assumption in engineering. After all, real-world signals have finite energies. Intuitively, when we also assume is uniformly continuous , the assumption of vanishing at |x|\rightarrow\infty is a logical conclusion, because otherwise how can the total area for |f(x)| be finite? An important outcome of this discussion is that the Fourier transform is unsuitable for periodic functions. Functions that repeat at intervals are not absolute integrable . For periodic functions, we use Fourier series. Some useful properties of Fourier transforms Linearity The Fourier transform is a linear operator, because the integral is linear: \[\begin{aligned} \mathcal{F}\left[\alpha f(x)+\beta g(x)\right]&=\int_{-\infty}^{\infty}\alpha f(x)e^{-i\cdot wx}dx+\int_{-\infty}^{\infty}\beta g(x)e^{-i\cdot wx}dx\\ &=\alpha\int_{-\infty}^{\infty}f(x)e^{-i\cdot wx}dx+\beta\int_{-\infty}^{\infty}g(x)e^{-i\cdot wx}dx\\ &=\alpha\mathcal{F}\left[f(x)\right]+\beta\mathcal{F}\left[g(x)\right] \end{aligned}\] So is the inverse Fourier transform; it’s similarly easy to show that: \[\mathcal{F}^{-1}\left[\alpha\hat{f}(w)+\beta\hat{g}(w)\right]= \alpha\mathcal{F}^{-1}\left[\hat{f}(w)\right]+\beta\mathcal{F}^{-1}\left[\hat{g}(w)\right]\] Scaling If we scale the domain of a function by a constant, its transform changes only slightly: \[\mathcal{F}\left[f(ax)\right]=\int_{-\infty}^{\infty}f(ax)e^{-i\cdot wx}dx\] Let’s do the variable substitution u=ax : \[\mathcal{F}\left[f(ax)\right]=\frac{1}{a}\int_{-\infty}^{\infty}f(u)e^{-i\cdot \frac{wu}{a}}du\] This is the Fourier transform evaluated at \frac{w}{a} , so: \[\mathcal{F}\left[f(ax)\right]=\frac{1}{a}\hat{f}\left(\frac{w}{a}\right)\] There’s one small caveat here; when a is negative, the integral bounds should be flipped, causing a minus sign in front of the transform. So we can write: \[\mathcal{F}\left[f(ax)\right]=\frac{1}{|a|}\hat{f}\left(\frac{w}{a}\right)\] Which works for any a\ne 0 . This property is intuitive when thinking about signals: suppose a>0 , then f(ax) means the signal is compressed in the time domain by a factor a . The scaling property says that the frequency domain is expanded using the same factor; in other words, the higher frequencies become more prominent because we need sharper transitions to represent the compressed signal. Time shifting What happens to the Fourier transform if we time-shift the input signal by some constant: f(x-x_0) . By definition: \[\mathcal{F}\left[f(x-x_0)\right]=\int_{-\infty}^{\infty}f(x-x_0)e^{-i\cdot wx}dx\] Substituting u=x-x_0 , we get du=dx , so: \[\begin{aligned} \mathcal{F}\left[f(x-x_0)\right]&=\int_{-\infty}^{\infty}f(u)e^{-i\cdot w(u+x_0)}du\\ &=e^{-iwx_0}\int_{-\infty}^{\infty}f(u)e^{-i\cdot wu}du\\ &=e^{-iwx_0}\mathcal{F}\left[f(x)\right] \end{aligned}\] Transform of a derivative An extremely useful property that’s often employed in the solution of partial differential equations; let’s calculate the Fourier transform of the derivative of : \[\mathcal{F}\left[f'(x)\right]=\int_{-\infty}^{\infty}f'(x)e^{-i\cdot wx}dx\] We’ll use integration by parts, where dv=f'(x) and u=e^{-i\cdot wx} . Therefore, v=f(x) and du=-iw\cdot e^{-i\cdot wx} : \[\mathcal{F}\left[f'(x)\right]=\left[f(x)e^{-i\cdot wx}\right]^{\infty}_{-\infty}-\int_{-\infty}^{\infty}f(x)(-iw\cdot e^{-i\cdot wx})dx\] Recall the assumption made in the "Existence condition..." section about vanishing at infinities. So the first part of the equation above is zero, and we’re left with: \[\begin{aligned} \mathcal{F}\left[f'(x)\right]&=-\int_{-\infty}^{\infty}f(x)(-iw\cdot e^{-i\cdot wx})dx\\ &=iw\int_{-\infty}^{\infty}f(x)e^{-i\cdot wx}dx\\ &=iw\cdot\mathcal{F}\left[f(x)\right] \end{aligned}\] Transform of convolution The convolution between two continuous functions and g(x) is defined as: \[(f\ast g)(x)=\int_{-\infty}^{\infty}f(\xi)g(x-\xi)d\xi\] Let’s calculate the Fourier transform of this function: \[\begin{aligned} \mathcal{F}\left[(f\ast g)(x)\right]&=\int_{-\infty}^{\infty}e^{-i\cdot wx}\left[\int_{-\infty}^{\infty}f(\xi)g(x-\xi)d\xi\right]dx\\ &=\int_{-\infty}^{\infty}\int_{-\infty}^{\infty}e^{-i\cdot wx}f(\xi)g(x-\xi)d\xi\ dx \end{aligned}\] This step of combining the integrals into a double integral, as well as the next step (changing the order of integration) is possible due to Fubini’s theorem and our assumption that and g(x) are Lebesgue integrable. Switch order of integration: \[\mathcal{F}\left[(f\ast g)(x)\right]=\int_{-\infty}^{\infty}\int_{-\infty}^{\infty}e^{-i\cdot wx}f(\xi)g(x-\xi)dx\ d\xi\] Now, f(\xi) in the inner integral doesn’t depend on x , so we can pull it out: \[\mathcal{F}\left[(f\ast g)(x)\right]=\int_{-\infty}^{\infty}f(\xi)\int_{-\infty}^{\infty}e^{-i\cdot wx}g(x-\xi)dx\ d\xi\] The inner integral is just the Fourier transform of a time-shifted g(x-\xi) , so we can write: \[\mathcal{F}\left[(f\ast g)(x)\right]=\int_{-\infty}^{\infty}f(\xi)e^{-i\cdot w\xi}\mathcal{F}\left[g(x)\right]d\xi=\mathcal{F}\left[g(x)\right]\int_{-\infty}^{\infty}e^{-i\cdot w\xi}f(\xi)d\xi\] And the remaining integral is the Fourier transform of , so: \[\mathcal{F}\left[(f\ast g)(x)\right]=\mathcal{F}\left[f\right]\cdot\mathcal{F}\left[g\right]\] Convolution in the time domain translates to multiplication in the frequency domain! This result is so important in signal processing that it’s called the convolution theorem . Appendix A: Riemann sum and the definite integral Suppose we have some function and we want to know the area bounded between this function’s graph and the x axis in a certain interval [a,b] . One way to do this is to take a partition of the interval: \[a=x_0<x_1<\cdots<x_{n-1}<x_n=b\] And calculate the area under for every element of the partition. We can then approximate such sub-areas by rectangles, as follows: We’ll denote the area of each rectangle as f(x^*_i)\cdot\Delta x : \Delta x=(b-a)/n is the width of one interval (assuming a uniform partition, but the math works just as well for non-uniform ones). x^*_i is some value in the interval [x_{i-1},x_i] .

0 views

📝 2026-07-14 23:24: I went for an 8km (5 mile) run this evening. I'm working my way up...

I went for an 8km (5 mile) run this evening. I'm working my way up to 10km, but I think this was a little too much, too soon. We'll see how my middle-aged joints are in the morning... Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views
DHH Today

Dell is on a roll with the XPS

We've been buying servers from Dell since the 2000s at 37signals, but I was never too impressed with their personal computers. They either felt cheap or enterprisey to me. Like they were made exclusively for people who are handed standard-issue laptops by corporate, and not something discerning techies would buy with their own money. But the new XPS line has completely changed my perception. I've now spent several months with the 2026 XPS 14 and 16, and last week I added the MacBook Neo-fighting XPS 13, and all I can say is that these machines are fantastic! Great chips, great screens, great build quality. Superb packages. Which is very satisfying to see because there are few American business leaders I respect more than Michael Dell. He's been running his company for over forty years now, and he's still calling the shots! So to see the company pull a turnaround like this, so many years into its run, is very inspiring. I've written about the XPS 14 before, and as I noted back in April, a good portion of the credit for these new Dell machines being really good belongs to Intel. The 18A process is paying big dividends for both companies (and the rest of the PC makers). But Dell could still have stuck these chips into forgettable machines, and I wouldn't have had any interest. In fact, they did! Just last year, for the 2025 model year, they shipped new XPS machines with awful capacitive-touch function and esc keys. Two years after Apple had finally thrown in the towel on the ill-fated Touch Bar on their MacBooks! Dell also killed the XPS branding last year, and went with the truly uninspired Plus/Premium/Pro copycat branding. Like some cheap Chinese knockoff. It was embarrassing, to be honest. But unlike Apple, which introduced that cursed Touch Bar back in 2016, and then crammed it down everyone's throat for seven long years, Dell rebooted this nonsense almost immediately. Gave us back real function and esc keys, and revived the XPS branding. You could argue that they should have learned from Apple's mistakes to avoid their own, but the next best thing is surely a quick reversal. And what a reversal it's been. As I said, I've spent months using an XPS 14 as my main machine. It's been so good I even gave up on using a dedicated desktop machine. Now I just run everything off the XPS 14, connected to an Apple XDR 6K 32" (nobody has yet managed to beat this, and I've owned it for years). It's a great, simple setup. The XPS 14 is an expensive machine, though. Not more so than its direct competitors, but still, at $2,799 for the 358H/32GB/1TB/OLED unit, it's a lot. I'd spend that in a heartbeat, but not everyone is going to drop that kind of cash on a laptop. Especially if they already have a powerful desktop. That's where the new XPS 13 comes in. It's part of the PC industry's answer to Apple's new MacBook Neo, which analysts all thought would catch the other side flat-footed. Well, surprise, it didn't! Apple charges $699 for an 8GB RAM/256GB SSD Neo, whereas Dell wants $699 for 8GB RAM/512GB SSD, and even offers a 16GB RAM/512GB SSD version for $899 (there's no RAM upgrade possible for the Neo). But matching Apple on specs and price wasn't the surprise; it was besting them with a nicer screen and keyboard, and meeting them on build quality. The XPS 13 has a great 120Hz screen (something you don't even get on a MacBook Air at twice the money!), a superb keyboard w/ backlighting (also missing on the Neo!), and weighs 20% less at just 1 kg with every bit as nice an aluminum chassis. Now I'd forgive anyone their skepticism about 8GB RAM and Windows. Microsoft isn't exactly known for creating a responsive operating system on modest specs these days, but who cares, we have Linux! Of course, I've been running Omarchy on this thing for the past week, and it's frankly fantastic. As long as you understand the limitations! The Intel Wildcat CPU uses the same performance cores as the full Panther Lake chip, so single-threaded snappiness is all there, but it only has two of those, and then another four low-powered cores. So six total, but not a mix that's conducive to running big multi-core workloads, like local CI. This is where the XPS 13 meets the moment. As the agent craze has been taking over software development, you might have seen any of the many memes about half-cracked laptops, just so the agents won't halt with a closed lid. The obvious answer is of course to run these agents off a home server in the closet, connect them to something as slim and light as an XPS 13 over Tailscale, and then control it all over SSH. Used like this, you get a machine that runs a browser as fast as anything on the PC (thanks to those full-speed performance cores) while costing a fraction of a new top-spec machine, and having better close-the-lid ergonomics. Win-win-hurray. When I posted my enthusiasm on X about this new XPS 13, I got at least three replies with "Is this an ad???". No. This is not an ad. I bought the XPS 13 with my own money, and frankly, you couldn't pay me any sum to use a laptop I didn't like. I did try Dell's laptops a few years back, didn't like what I saw, and ended up spending a few years using Framework computers instead (they're still great too). I'm simply excited that the PC isn't giving up without a fight. That Linux has been on a run among early adopters. That companies like Intel and Dell are here to keep Apple honest. Competition is great. It was Apple's M chips that rejuvenated the laptop market, and they held a supreme lead for years. So it's lovely to see Intel, Dell, and others actually being ready to meet the challenge from the low-cost Neo right out of the gate. So I tip my hat, once again, to Michael Dell. Forty-plus years at the helm, not too proud to pivot quickly, and now the maker of my favorite Linux laptops. Well done, sir.

0 views

Workshop Basel day one

On this hot summer’s day in Basel, Switzerland, the seventh HTTP workshop started. These events tend to work roughly the same way and the people in the room are also to large extent familiar and known since previous editions. Forty people in a meeting room, where we take turns in doing short talks on HTTP and networking topics, with the following question and discussion session. The rules for the meetings are explicitly Chatham rules, which means that everything I write about the meeting will be sufficiently fuzzy and without many company or personal names. This is not the kind of meeting that can be easily summed up in a short blog post anyway. You really should be here. Present in the room were representatives from all the world’s most prominent and used HTTP deployments: clients, browsers, CDNs, proxies and servers. I’m happy to say that there were also several first-timers. We like fresh blood. (If you think I’m being overly brief or vague about specifics in this post; that is partially on purpose but primarily because I’m a lousy note-taker and mostly write this up after a busy day that also may have involved beer.) After a round of introductions, we started. REST is a set of constraints, and in this presentation it was argued that it can or maybe even should be extended to do more. A number of recent applications like Mastodon/ActivityPub, Bluesky/AT, Matrix, Nostr, IndieWeb, all currently use HTTP to do state synchronization but they all do it differently in their own unique ways. Can REST and maybe HTTP be adjusted to help this for improved interoperability? Looking at the Common Crawl data and comparing data over time, it was observed that responses use the Last-Modified header field more now than they did in the past, and there were great follow-up speculations on why this is so. Data also shows that a large share of these headers present dates that are almost identical to the time the requests were issued. With the cc-lint tool , data was gathered on how HTTP is actually used today, proving that there is work to be done: deprecated headers are used, some headers are done wrong, and many are overly big. This indicates that there are well used both servers and clients out there that would benefit from cleanup. It probably also shows that doing HTTP correctly and all the correct headers is far from an easy task. Another presentation showed data, this time from a well-known CDN, on the impact the existing AI scraper bots have on the Internet from their point of view. It showed that roughly half of the requests and half of the bandwidth are spent by scraper bots. A long discussion followed where the numbers were questioned as maybe the numbers look like this because a sufficiently large number of the “bad AI scrapers” appear as regular users to the classifiers. Speculations of different kinds were made.  As a follow-up from a presentation from a previous HTTP workshop we got to learn how the journey on developing their new HTTP stack has progressed and several fun adventures and lessons from that were shared with the audience. A look into new HTTP API development at Apple . Some discussions and lessons learned from creating new APIs for both servers and clients. We got an excellent walk-through of some details and internals of the Android networking stack. Emphasis was perhaps especially put on ECH and QUIC connection migration, and the final “don’t tell us when your connection closed” led to a long new discussion on how we really should fix the problem: when connection has been left idle for a long time and it is closed by the server, the client (mobile phones) don’t want to be told. This, because getting that RST and more, just wakes up the radio and more on the phone only to tell it to go back to sleep. It was theorized that if we could get rid of this unnecessary battery waste, the accumulated gain across billions of devices would make a serious dent. Several additional HTTP related problems were of course also subsequently solved as we then wandered into the city for dinner and maybe a beer. Of course yours truly returned back to his hotel room in good time to be able to write up this blog post. The best part of these workshops might be the (no pun intended) networking and discussions had completely outside of the agenda. End of day one. Two more to come,

0 views
Unsung Today

Sets of overlapping circles

This is a design joke that always makes me laugh: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/sets-of-overlapping-circles/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/sets-of-overlapping-circles/1.1600w.avif" type="image/avif"> This was made by… someone, a while back, I believe in response to the Twitter logo redesign of 2012, which showed the new logomark as composed of exclusively circles: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/sets-of-overlapping-circles/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/sets-of-overlapping-circles/2.1600w.avif" type="image/avif"> Now, to be clear: that Twitter logo redesign was gorgeous, and I do not particularly care if it was designed out of circles or whatever else. I don’t even think its announcement was presented in a overly pretentious way – it was nowhere near the 2008 bloviating Pepsi redesign or the rank amateurism of Yahoo’s new 2013 logo . It’s just… design can be so pretentious and up its own golden-ratioed ass, and I can’t help but love anything piercing that bubble. (In my perfect, naïve world, Doug Bowman – the designer behind the logo – also finds the joke hilarious!) Also, I feel like design is just not… funny, all that often. Quick, think of any product design joke. See what I mean? I can’t, either. My favourite graphic design joke is “if it’s big and ugly, it’s not big enough.” (You know, it’s funny because it’s sad.)

0 views

Microsoft Patches a Record 570 Security Flaws

Microsoft Corp. today released software updates to plug at least 570 security holes in its Windows operating systems and other software, almost triple the number of vulnerabilities the software giant fixed in its record-smashing Patch Tuesday release last month. Microsoft attributed the burgeoning patch counts to vulnerability discoveries aided by artificial intelligence. Nearly 60 of the bugs quashed in July’s Patch Tuesday earned a “critical” severity rating, meaning miscreants or malware could use them to seize remote control over a Windows device with little or no help from the user. Microsoft also addressed three zero-day flaws, including two that are already being exploited in the wild. Two of the zero-day weaknesses allow an attacker to elevate their user rights on a Windows system, as do approximately 250 other elevation of privilege flaws fixed this month; they include CVE-2026-56155 — an Active Directory Federation Services bug — and CVE-2026-56164 , a Microsoft Sharepoint vulnerability. CVE-2026-50661 is a security feature bypass in Windows BitLocker that could allow attackers to gain access to encrypted data if they have physical access to the device. Microsoft said this bug has been detailed publicly, but that it is not aware of any active exploitation. In a blog post on July 9, Microsoft Executive Vice President Pavan Davuluri wrote that Windows users will notice “a higher volume of security updates included in each security release” as a result of AI aiding in the discovery of vulnerabilities. “The pace of vulnerability discovery is changing with advances in AI making it possible to find more issues, faster, across more code, with new mechanisms that can accelerate both discovery and analysis,” Davuluri wrote . Jack Bicer , director of vulnerability research at Action1 , called attention to CVE-2026-48561 , a remote code execution flaw in Microsoft Copilot (with a 9.6 CVSS threat score) that allows an unauthorized attacker to execute code over the network. Microsoft says an attacker could exploit this bug by hosting a malicious website that causes Microsoft Edge for Android to automatically send crafted prompts to Copilot when a user visits the site. As AI advances the state of vulnerability discovery and remediation, it is also making it easier for attackers to quickly devise working exploits for known software flaws. Microsoft has long labeled security bugs using its “exploitability index,” which is Redmond’s best guess as to how likely it is that attackers will be able to figure out a reliable way to exploit a given vulnerability. But Satnam Narang , senior staff research engineer at Tenable , argues that Microsoft’s exploitability index needs to do a better job of shifting with the machine speed of discovery. For example, Microsoft originally gave this month’s SharePoint zero-day an exploitability rating of “less likely,” although the flaw was added to CISA’s Known Exploited Vulnerabilities list on July 1. “Anthropic’s Red Team’s own findings for known vulnerabilities (n-days) revealed how fragile this system has become, with its Mythos Preview model being able to produce proof-of-concept exploits for 13 of 14 vulnerabilities that were rated ‘Exploitation Less Likely’ or ‘Exploitation Unlikely,'” Narang said. “What this means is that our way of looking at Patch Tuesday has changed, because the exploitability index is centered around humans, not AI tools, and as these tools continue to improve, defense needs to improve alongside it.” Chris Goettl at Ivanti observed that the record patch numbers from Microsoft come as a number of other major software makers are increasing their patch cadence, including Adobe which announced today it is moving to twice-monthly security bulletins published on the 2nd and 4th Tuesday of each month (Adobe also cited AI for accelerating their patch cycles). Cisco , Mozilla and Oracle also are shipping updates more frequently, while Google’s patch batches in June 2026 totaled more than 900 security fixes, Goettl noted. Backing up your Windows system and/or data is always a good idea before applying operating system updates. Given the volume of patches addressed this month it may be wise for end users to wait a few days before applying these fixes. It’s not uncommon for security patches to introduce system stability issues, and those chances probably increase quite a bit with the gigantic patch count released today. Further reading: Action1’s Patch Tuesday blog Automox’s rundown

0 views
Pete Warden Yesterday

Launching Moonshine Micro

Long-time readers will know I’m convinced local voice interfaces and sub-$1 embedded chips will fundamentally change how we interact with everything in the physical world. That’s why I’m so excited to introduce Moonshine Micro , a version of the Moonshine Voice open source framework that can run a useful voice interface in just 520KB of RAM. It contains separate libraries for voice-activity detection , speech to text , and text to speech , all powered by tiny neural networks with an example bringing them all together on an 80 cent Raspberry Pi RP2350 chip . I’m still working towards the end goal of the moonshot I started at Google Brain in 2017, a full ASR and TTS system on a 50 cent chip that can run on a coin battery for a year, but this is a big milestone on the journey. This release runs a 50-word command recognizer, that’s fully trainable for custom words , and a neural network-based text to speech engine, and can be used to set up a wifi connection. There’s still a lot of work to do to increase the scope of the recognition to full speech, rather than individual words, increase the text to speech quality, and to offer advanced intent recognition on this kind of system, but with the hardware improvements that are likely to come over the next few years, I think we’re getting a lot closer. I’m looking forward to seeing applications I’d never thought of for this technology, so if you build something neat please tag me on Hackster, and for questions or issues let me know on GitHub .

0 views
Unsung Yesterday

“Cursed knowledge we have learned that we wish we never knew.”

Immich is a self-hosted photo/​video app, and one of their side pages is Cursed Knowledge : Cursed knowledge we have learned as a result of building Immich that we wish we never knew. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/cursed-knowledge-we-have-learned-that-we-wish-we-never-knew/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/cursed-knowledge-we-have-learned-that-we-wish-we-never-knew/1.1600w.avif" type="image/avif"> There is something about this format that I really enjoyed as a reflection but also as a way to share with others – simple one sentence/​paragraph updates with links, so you can inhale quickly but also go deep if needed. There’s some overlap with bugs here, but it’s not necessarily only buggy stuff – also quirks of formats, observations, etc. I made a cursed knowledge page for Unsung – let me know! (Thanks to Casey Gollan for posting about the original page.)

0 views
Unsung Yesterday

“If HEIC has no haters I’m dead.”

Over on Bluesky, Melanie Walsh asks : Favorite and least favorite file formats? I’ll start. Favorite: TXT Least favorite: HEIC The answers – both replies and quote posts – are really interesting because most of the time they’re not about inherent capabilities of each format, but: Of course, Walsh put a finger on the scale with her initial example, but HEIC stands out as a favorite least favorite. I understand this is mostly out of its limited support, raising a question whether Apple spent the right amount of time socializing and incentivizing its adoption – even on a Mac, you can’t escape blank stares the moment you drag it into many websites/web apps: HEIC on the other hand, Apple’s way of making photos smaller and everything else more complicated than it needs to be. By the way HEIC is when you drag a picture from your Notes app into your email, and then it laughs in your face and is like sorry, girl, I’m HEIC!! I don’t do things like that!! I didn’t know I had a least favorite file format but yeah HEIC can fuck right off Sweet fucking hell fuck heic into the sun Reading the replies here makes me feel like I live in an oddly privileged bubble in an inverse of the usual meaning of privilege for being a poor Android-using mfer who has never seen a HEIC in their life and had to actually look that sh*t up. Least favorite is a toss up between HEIC (WHICH NOBODY ASKED FOR, APPLE) and WEBP Controversial but I hope everyone involved with HEIC only tastes soap instead of cilantro forever I agree with this person that WebP is much better supported than it used to, but it sometimes takes one link in the chain – cough Google Docs cough – for you to avoid a format forever. And, those are always lagging indicators. If a format didn’t work once in an important flow, it might take many years before you come back: all the people saying “webp” in the quotes might as well be fighting WW2 still. look for another grievance. please Some other fun answers: IF IT’S CALLED [C]OMMA [S]EPARATED [V]ALUES WHY DO I HAVE TO OPEN A WINDOW AND CHANGE THE DEFAULT DELIMITER OPTION FROM TAB TO COMMA ??!?!?! Favorite: MP3 (invented piracy, patents all expired, doesn’t need an FPU) Least favorite: DICOM (nightmarish metadata, too many possible image encodings, when it wants a 3D volume the solution is just “a bunch of files in a folder”, also IT IS A NETWORK PROTOCOL >:( ) Least fave: .R01, .R02, etc... – nothing needs to be split into multiple rar files! Please stop! The world has moved beyond this. Least favorite: can I count those awful pointer doc types Google uses, like .gdoc and .gsheet favorite: transparent PNG least favorite: transparent PNG that is not really transparent but just a fuckin checkered background I forgot about this meme: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/if-heic-has-no-haters-im-dead/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/if-heic-has-no-haters-im-dead/1.1600w.avif" type="image/avif"> For least fav I voted for GIF, having not only spent countless hours trying to make good-looking animated gifs that do not weigh tens of megabytes, look horrible, and cause performance issues… but also having worked on two different products (Medium and Figma) that had to swallow gifs made by others, and seeing engineers lose their minds peeking into their insides and how messy they were . To be fair, GIF comes from the late 1980s, and simply outlived its purpose. It’s a fascinating format that literally deserves a book written about it: the messy patent wars, the pronunciation, the technical format and many surprises hiding inside , even the word “gifs” transcending the format itself to mean “short animated memes.” To go back to the thread, a small pattern that I also encountered from time to time: Least favorite: .md, specifically when it’s used for Sega Genesis game roms. There’s already a type of text file type called .md, so Windows tries to open them in notepad. Just call it .gen instead, nerd. Favorite: TS, the one that opens in my IDE Least Favorite: TS, the one that opens in Quicktime Lastly, because of course someone had to do it: Favorite: Gaylord Archival® Reinforced Acid Free Manilla Least favorite: Office Depot Vertical Hanging Folders #encoding #graphics #software evolution how well supported it is in the general ecosystem? how painful it was last time I used it? who’s using it and for what? if there is one app I use it with, do I like this app? (interesting in the context of PDFs which some people love, and others hate)

0 views
Martin Fowler Yesterday

DSLs Enable Reliable Use of LLMs

LLMs generate code incredibly fast, but to ensure they generate exactly what is intended, they need clear boundaries. Abstractions and Domain-Specific Languages (DSLs) provide a strong harness that guides LLMs right from the start. Unmesh Joshi describes how the example of Tickloom - a domain model and DSL for illustrating distributed system behavior - shows how we can use an LLM as a partner to iteratively build a DSL and as a natural language interface to use it. Such a DSL can act as the key source of truth for software systems in the world of LLMs.

0 views

RABIT: Efficient Range Queries with Bitmap Indexing

RABIT: Efficient Range Queries with Bitmap Indexing Junchang Wang, Fu Xiao, and Manos Athanassoulis SIGMOD'26 This paper presents an optimization for range filtering (e.g., ). File this under: “so crazy it might actually work”. This paper builds on the concept of a bitmap index . If the cardinality of a column is (i.e., there are distinct values in the column), then a bitmap index stores additional 1-bit columns along with the original column. These additional columns are called point bitvectors . The value in additional column is 1 for a particular row if the value in that row is the th distinct value. Here is an example column with 6 rows and 4 distinct values (0, 1, 2, 6). The header indicates that this is the value column. And here is the same column with 4 additional 1-bit wide rows attached. The header indicates columns that hold point bitvectors. To find all rows which have a value of 2, simply read the 3rd (i.e., ) bitmap column. Similarly, to find all rows which have a value of 6, simply read the 4th bitmap column. To efficiently support range queries, the authors of this paper propose adding even more columns that hold 1-bit values. These columns are called cumulative bitvectors . A cumulative bitvector holds the bitwise-or of a set of point bitvectors. In the example above, let’s create a cumulative bitvector (named ) for the values 0 and 1. The value of this column for a given row will be 1 if the value contained in the row is either 0 or 1. In other words: . Similarly, we can create a cumulative bitvector for the values 2 and 6 using the equation: . Here is the full turkey: A range query can be executed by reading one or more cumulative bitvectors and possibly a few point bitvectors. For example, to find all rows that have a value < 2, all one needs to do is read the value of . Cumulative bitvectors do not add much value in this toy example because each cumulative bitvector only aggregates data for two values, but you can see how this could work well with more aggregation. This trick can even be made to work for range queries that partially overlap with a cumulative bitvector. This whole scheme relies on the fact that point and cumulative bitvectors are highly compressible. This paper assumes the use of WAH compression . The executive summary of WAH compression is to divide each bitvector into words (e.g., 32 or 64 bit). One bit of each word is metadata that determines if the word is a or a . The remaining bits of a literal word contain raw (uncompressible bits). The remaining bits of a fill word contain a value and a length (run-length encoding). Fig. 9 compares throughput of this scheme (labeled GE in the figure) to other work. means each cumulative bitvector aggregates data for 20 point bitvectors. Performance looks good even for columns holding 100K distinct elements. Source: https://dl.acm.org/doi/10.1145/3769819 Table 3 compares the storage requirements for this scheme versus other indexing schemes that support range queries, which seems too good to be true. Source: https://dl.acm.org/doi/10.1145/3769819 Dangling Pointers I wonder if this idea could be generalized to other types of filtering, such as string operations (e.g., . Thanks for reading Dangling Pointers! Subscribe for free to receive new posts.

0 views
Stratechery Yesterday

The OpenAI Super App, ChatGPT = Codex, Whither Chat

OpenAI has refashioned Codex as the new ChatGPT; is the company abandoning the chat category they pioneered?

0 views
マリウス Yesterday

The Day WhatsApp Goes Dark

Note: As usual, tl;dr at the end. Tomorrow morning, WhatsApp goes dark, and it’s not just a short downtime, but it is a termination of the service. The servers turn off, the domains don’t resolve anymore and no mobile client is able to connect. Have you ever asked yourself what would happen in that case? What if WhatsApp actually went dark? Obviously, nobody really knows what would happen in such a case, because we haven’t experienced that situation (yet), but even though the closest analogues like the six-hour Meta outage in October 2021, and Brazil’s 12-hour court-ordered shutdown in December 2015 were measured in hours, not days, those already produced effects that journalists described as “apocalyptic” . We can try to extrapolate what happened throughout events like those to see what “global catastrophe scenario” could theoretically look like. Because whether you believe it or not, WhatsApp is more than just a messenger , and one example that makes this pretty obvious came from the Forbes editor José Caparroso , who wrote during the 2021 blackout that … Latin America lives on WhatsApp . I am surprised by so many people underestimating how catastrophic this downfall has been. But before we dive into this thought experiment, however, it’s worth establishing what we’re actually talking about, as readers in most of Europe and North America underestimate WhatsApp by an order of magnitude, primarily because in those markets it functions as one platforms among many. That is, however, not how the rest of the planet works. Note: This thought experiment is not only based on some abstract numbers and studies, but upon my own experience of how WhatsApp is being used in e.g. the global south on a day to day basis. During my travels I think I’ve pretty much “seen it all” , with for example broadband technicians taking photos of the stickers on the backside of WiFi routers/modems, that show the hardware address and login credentials (on their phones), and sending them via WhatsApp to themselves, only so they can open them on WhatsApp Web (on their work laptops), in order to upload them into the ISP’s technical service portal. It is frankly mind-boggling what sort of tasks WhatsApp has become a Swiss army knife for in those countries, whether it’s as a file transfer platform for sensitive documents, or as a full-blown hotline for critical services and infrastructure. Let’s start by understanding the sheer scale of WhatsApp . The Meta owned and operated messenger has roughly 3.3 billion monthly active users as of early 2026, which is about 40% of every human alive, and somewhere north of 60% of every human with a smartphone. The platform processes more than 100 billion messages per day , out of which around 7 billion are voice messages. On top of that, users place around 5.5 billion voice calls and 2.4 billion video calls per month , which boils down to more than 2 billion minutes of voice and video traffic every 24 hours. To put this in perspective, the global SMS network, at its peak in 2012, handled about 23 billion messages per day across every carrier on Earth. WhatsApp does four to five times that volume on its own, every day, on a service that is (at least at the consumer layer) “free” . However, if we look deeper into the country-level breakdown, it becomes clear that WhatsApp usage isn’t evenly distributed across the globe. India has between 535 million and 596 million monthly active users , and regardless of whether we pick the higher number or we stick with the more conservative estimate, it is the largest single national user base on any messaging platform anywhere. Brazil has about 148 million users, and the app is installed on roughly 99% of the country’s smartphones. And 93% of those users open the app daily . Indonesia has about 112 million users, with WhatsApp being the leading messaging platform in the country, and in Zimbabwe WhatsApp alone accounts for roughly 44–50% of all mobile internet traffic . In Lebanon more than four in five adults use it , making it the dominant communications channel during multiple national crises. In a great many countries, WhatsApp is not simply a service on the internet, it actually is the internet for most practical purposes. WhatsApp Business now has more than 200 million businesses on the platform globally , with around 50 million small and medium-sized enterprises using it as their primary customer channel. In India and Brazil, roughly 80% of small businesses use WhatsApp to communicate with customers. In Brazil specifically, 96% of businesses rate WhatsApp as their primary communication tool, and a joint study by Fundação Getulio Vargas and Sebrae , Brazil’s main small-business support organisation, found that 70% of Brazilian small companies rely on the Meta -owned trinity ( WhatsApp , Instagram , Messenger ) as their marketplace. Globally, around $45 billion in commerce is expected to flow through WhatsApp in 2026 . Click-to-WhatsApp advertisements alone generate roughly $10 billion per year for Meta . About 175 million customers send messages to WhatsApp Business accounts every single day. And then there’s payments. In India, WhatsApp Pay is a small player in the UPI with about 67 million transactions per month against UPI’s 18 billion monthly volume, but in absolute terms, that’s still an enormous number of transactions. In Brazil, WhatsApp Pay is integrated with local card and bank rails and is used by transit operators ( Vai de Bus , for instance, sells passes via WhatsApp ), banks, and merchants. Across Africa, fintech overlays on WhatsApp , like Finnova in Nigeria, or Azza in Nigeria, Kenya, and South Africa, are processing crypto and conventional payments at significant volumes. Besides being a chat platform, a marketplace and a payment processor, WhatsApp is also being used as critical clinical infrastructure across the global south. A three-year programme at UCLA’s David Geffen School of Medicine paired subspecialists in Los Angeles with clinicians at Partners in Hope Medical Center in Lilongwe, Malawi, via WhatsApp groups. 89% of submitting clinicians and 71% of expert respondents reported that the case discussions improved medical education and patient outcomes. In the Eastern Cape of South Africa , WhatsApp groups serve as the primary continuing-medical-education channel for HIV and TB management in rural clinics where specialists are days away. In Haiti, WhatsApp groups coordinate emergency department operations at Hôpital Universitaire de Mirebalais , including mass-casualty alerts, security updates, and clinical decisions. In Zambia, IntraHealth International runs nurse and midwife mentoring networks over WhatsApp . In Brazil, the link between Zika virus infection and microcephaly was tracked partly through WhatsApp groups of paediatricians comparing cases. Another critical field that runs on Meta ’s infrastructure is disaster response. The World Bank documented that during 2014’s Cyclone Hudhud in Andhra Pradesh, India , the Public Works Department restored connectivity to a 1.8-million-person city primarily by coordinating engineers through a closed WhatsApp group with the District Magistrate in it, without any formal meetings and orders, which ultimately led to most roads becoming functional within three to four days. During the 2023 Turkey earthquakes, volunteer-formed WhatsApp networks processed 5,800+ messages in one week for needs assessment and rescue, and in Syria, the White Helmets have run an emergency dispatch system over WhatsApp since 2021, because the country’s emergency number infrastructure is largely destroyed and WhatsApp ’s compression algorithms work where almost nothing else does. It’s not just individual organisations, but even whole governments are dependent on Meta . Buenos Aires for example ran a COVID-symptom triage chatbot on WhatsApp , and Lebanon’s public health ministry launched an automated WhatsApp service in April 2020 to disseminate updates on the pandemic. India, on the other hand, offers metro tickets, government services, and bill payments through WhatsApp chat interfaces . On top of that, for example, the Philippines’ UAE consulate operates consular emergency hotlines on, you guessed it, WhatsApp . Last but not least, there’s migration. Roughly a quarter-billion people live outside their country of birth. Most of them use WhatsApp as their primary connection to family, because international SMS is expensive and unreliable and Skype is, well, dead. Multiple peer-reviewed studies on Trinidadian , Pakistani, Ghanaian , Polish, and Kenyan diasporas also converge on the same finding of WhatsApp being the primary technology of transnational family life in 2026. So to go back to our initial thought, let’s imagine WhatsApp shutting down in an instant, with this dependency graph in mind. What follows is a hypothetical scenario sketched from the documented impacts of past (shorter) outages, scaled up by the duration and finality of the event, and informed by the dependency layers described above. It’s a scenario and not an actual prediction. The shutdown hits during European afternoon, which means American morning, Indian evening, East African afternoon, and Indonesian late evening. The first signals show up on Downdetector and on non- Meta competitors. In 2021, the six-hour outage generated 14 million reports inside the first few hours, but this time the number is likely much larger. Behaviour inside the first hour is uneven and largely confused. In most places, users assume it’s a routing problem, a local carrier issue, or a phone bug. They restart the app, then their phone, then their router, then they check Twitter X , Instagram , TikTok , Telegram , maybe Signal , or Facebook Messenger , depending on what they have installed. Telegram and Signal both see app-store download spikes within the first 30 minutes, as it happened during the 2021 outage, with Signal reportedly adding “millions” of users that day . The first noticeable failures show up in commerce. A food-truck operator in São Paulo who takes orders via WhatsApp can no longer receive them. A small clothing brand in Mumbai whose entire sales pipeline runs through Click-to-WhatsApp advertisements sees its ad spend continuing to bill while the conversation endpoint returns errors. In Hong Kong, a logistics coordinator who confirms container pickups via WhatsApp loses the day’s confirmation chain. In Idlib, Syria, the White Helmets dispatch room realises within minutes that emergency calls are not coming in, and civilians have no fallback channel. It is likely that three things start happening in parallel. First, mass migration to apps like Telegram , Signal , and to a lesser extent Messages ( iMessage ), Viber , and Line . Signal ’s servers, which are run on a fraction of WhatsApp ’s infrastructure, are not designed for an inrush of hundreds of millions of new accounts and start to degrade in some regions. Telegram , which has spent a decade preparing for exactly this scenario, holds up better but still struggles with its own issues. Ultimately none of the alternatives are suitable for the people who had built their workflows on WhatsApp . The second thing that happens is commercial collapse , which is the biggest 12-hour story, but still largely invisible from Western media. In Brazil, Indonesia, Nigeria, India, Pakistan, Bangladesh, Vietnam, Mexico, and probably 50 other countries, the small businesses that route everything from orders and prices, and photos of goods, to delivery confirmations, and payments, through WhatsApp have lost their primary revenue channel. A clothing brand in Ireland reportedly lost thousands of euros in a single afternoon during the 2021 six-hour outage. Multiply this by twelve hours and by the entire tail of informal commerce that lives on the platform and the figure runs into the billions. The third thing is health-system stress . Group consults that normally take an hour over WhatsApp become almost impossible. The Eastern Cape HIV-management network in South Africa, the Malawi-UCLA clinical link, the Haitian ED coordination groups, the Zambian rural-nurse mentoring channels, all degrade simultaneously, and while mortality consequences are not yet visible, they are happening nonetheless. In several countries, government officials begin issuing statements through whatever channel is still functioning. After the first 24 hours it becomes clear that the impact this situation has is roughly inversely proportional to a country’s investment in alternative digital infrastructure. The United States and Western Europe are mildly inconvenienced, and India is moderately disrupted, mainly because the country has built duplicate rails, hence UPI runs over many apps. After all, SMS still works, alternative payment apps exist, and government services have their own portals. However, countries like Brazil, Argentina, Mexico, and most of sub-Saharan Africa, on the other hand, are in serious trouble. In Brazil, by the end of day one, the financial press is comparing the situation to a partial shutdown of the national payments system. Pix transfers still work, as those run over the central bank’s infrastructure and not WhatsApp ’s, but the merchant-customer communication layer that drives Pix transactions for millions of small operators is offline. The same is true in Argentina, where the inflation-driven culture of constant price renegotiation between vendors and customers happens, in practice, almost entirely on WhatsApp . Another area that starts to fail is migrant remittance. People working in the Gulf, North America, or Europe typically coordinate transfers with their families via WhatsApp , where they confirm the recipient’s details, send screenshots of receipts, or sometimes route the money through informal Hawala -style networks where trust is established and maintained by daily messaging. These workflows don’t fail completely on day one, but they slow and break in ways that don’t show up in formal remittance statistics for another week or two. In Latin America, the first major political consequence appears in the form of misinformation that previously circulated within closed WhatsApp groups , which now has nowhere to go and starts spilling onto other platforms. By the end of day one, more than 100 million people have created Signal or Telegram accounts. Both apps experience their first significant performance degradation events. The labour-market consequences start showing up. In India, where WhatsApp is the de facto recruiting and onboarding tool for huge segments of the informal economy, gig workers can’t be reached for shifts. Delivery platforms like Swiggy , Zomato , Dunzo , and their international equivalents, see their dispatch coordination degrade. Some of these companies have parallel in-app messaging, but many have leaned hard on WhatsApp because it was cheaper. Schools also begin to feel it, because in many countries, including India, Brazil, South Africa, Kenya, Nigeria, the Philippines, Indonesia, and much of the Middle East, parent-teacher communication runs over WhatsApp groups. Two days in, schools that have not made the switch to other channels are operating partially blind, and parents are not getting closure notifications, transport updates, fee reminders, or exam schedule changes. In countries with weak alternative communication infrastructure, the second-order effect is mid-week absenteeism as parents simply don’t know whether school is open. On top of it all, Healthcare is also heavily impacted. For example, the Haiti emergency-department-style coordination groups have now had 48 hours to find alternatives, and they have, mostly, but the transition has costs. Case discussions that were asynchronous and 24/7 on WhatsApp are now synchronous and harder to schedule, and rural clinicians in places like the Eastern Cape, Lilongwe, or the highlands of Nepal are once again practising in the relative isolation that WhatsApp ’s group-call and group-message features had alleviated. In several documented studies, isolation correlates with diagnostic delays and worse patient outcomes. In Syria, the White Helmets switch to a patchwork of Signal , SMS where it works, and physical runners, and response times degrade significantly. At this point things start to get political. In a number of countries, including Brazil, India, Indonesia, Nigeria, the Philippines, and South Africa, the question stops being “what is Meta doing” and starts being “why did we let one foreign company become this central” . Telecom operators in several countries pitch the moment as an opportunity to push their own messaging products, most of which have been moribund since 2014, but the pitches fail because nobody trusts the carriers, because those carriers have been quietly delighted to see WhatsApp gone, given that it eroded their SMS and voice revenue for a decade. In a few markets, regulators float emergency-decree-style proposals to nationalise messaging infrastructure or build sovereign alternatives. And while most of these proposals are clearly performative, some are not. India and Brazil both have working national digital identity and payments stacks that could, in principle, host a public messaging layer. It remains to be seen, though, whether the political will to build one persists past the first month. Public health authorities in Lebanon, Buenos Aires, the Philippines, and several African countries are now running emergency communication operations across multiple fallback channels. None of them work as well as WhatsApp did and things like vaccination schedules are missed, and appointment reminders fail. Some clinics see patient no-show rates rise by 30–40% versus baseline. Not because WhatsApp is superior to its competitors, but simply because humans need a long time to adjust to the alternatives that are being put in place. Also, crime patterns shift in interesting ways. A Conflict Sensitivity Resource Facility report on South Sudan, and PeaceRep work on Somalia, both documented that WhatsApp groups were used for both peace-building and for coordinating violence. Removing the platform doesn’t remove either function, as both migrate to other channels, but the migration takes time, and during the transition, coordination of all kinds becomes harder. In several markets, online ad spend collapses because Click-to-WhatsApp ads (a $10B/year business) have no destination, and Meta ’s stock price has already done what you’d expect it to do. The migration to alternatives, mostly Telegram and Signal , with regional pockets going to Line , KakaoTalk , WeChat , Messages ( iMessage ), RCS , and a long tail of smaller apps, has now hit critical mass in most of the world. The migration has not been clean, and group chats with over 200 members have, in practice, often migrated as group chats with around 40 members, because not everyone moved at the same time or to the same app. For business communication, the new world is as fragmented as it gets. A Brazilian shopkeeper who used to take all orders on WhatsApp now has to manage Telegram , Signal , Instagram DMs (still up, but reduced after Meta ’s reputational damage), and SMS. Customer-acquisition costs rise, and customer-retention drops, and several reporters publish stories on small businesses that have permanently closed. For healthcare, the migration is more orderly because the user base is smaller and more motivated. Most major peer-support networks, like the Malawi-UCLA , the Eastern Cape HIV , the Zambia nursing , and the Haiti emergency have stable new homes. The five-day disruption produced measurable degradation, and it is not yet possible to quantify the mortality and morbidity impact. In Syria, the White Helmets have built a partial replacement on Signal and on a custom dispatching tool that their engineers had been prototyping. It works less well than what they had, because the compression behaviour that made WhatsApp viable in low-bandwidth, intermittently-connected environments is hard to replicate. Hence, some dispatches are now arriving via paper notes. Not because decentralized mesh networks don’t exist, but simply because nobody in these organizations has the expertise to implement these alternatives, especially within such a short period of time. The first credible economic estimates of the shutdown’s cost reach the tens of billions of dollars and continue to rise. The estimates are dominated by long-tail effects in emerging markets that are hard to measure precisely. A week in, the question has shifted from “When does WhatsApp come back?” to “What does the world look like without it?” and a growing fraction of the user base assumes it isn’t coming back, so behaviour begins adapting accordingly. Several governments, including Brazil, India, and the EU as a bloc, have announced formal investigations or task forces into how to prevent this from happening again. As usual, however, none of them will produce anything actionable within years. The longer-term effects, that you can already see the shape of by day seven are a measurable productivity hit in emerging markets, particularly for informal-sector businesses, a consumer trust impact across the entire Meta product family, a wave of WhatsApp-replacement startups, most of which will fail due to network effects and generally bad engineering, and the painful realisation that a free product is not the same thing as a public good. Some estimates from prior outage studies suggest that a six-hour WhatsApp outage cost the global economy hundreds of millions of dollars per hour in lost SME activity, weighted heavily toward Latin America, South Asia, and Africa. Extrapolated over seven days and weighted for cascading effects, the seven-day damage is in the tens of billions, possibly higher. This thought experiment is not about Meta eventually shutting down WhatsApp , as it almost certainly won’t do so on its own, given how big of a lever the platform is for the company. In fact, Meta is moving in the opposite direction, as it is building WhatsApp Business into a $45 billion commerce platform, integrating it with payments, and turning ads into one of its fastest-growing revenue lines. WhatsApp is too valuable to Meta to switch off voluntarily, and the regulatory regimes in the countries that depend on it most are nowhere near coordinated enough to force a switch away from it or even just ban it outright. The point is that we have built a planet-spanning piece of communication infrastructure whose ownership, governance, and continuity are concentrated in a single American corporation, that is led by people with questionable values and beliefs, which all in all is a state of affairs that has no historical precedent. Sure, there are other US-based companies that “own digital communications” , like Twitter X and many others, albeit I’d argue that none of those platforms are so engrained into everyday life across many (predominantly developing) nations as WhatsApp is today. The closest analogue in scale is the global SMS network of the early 2000s, which, however, was federated, run by hundreds of carriers and governed by an open standard (GSM/3GPP). SMS was never under the unilateral control of any single entity, despite many carries enjoying a defacto monopoly in their respective home markets. WhatsApp , on the other hand, is a single proprietary protocol, with a single operator, optimised increasingly for the commercial interests of that operator, and treated by the rest of the world (governments, hospitals, schools, small businesses, families separated by borders) as a public utility. The seven-day scenario above is an exercise in realising this dependency. Meta has no public-service mandate and WhatsApp ’s terms of service explicitly disclaim any commitment to availability. Yet a meaningful fraction of the medical communication, emergency coordination, family contact, and small-business activity of the global south runs on top of this disclaimed-availability infrastructure. At this point the LinkedIn thought-leadership crowd would tell you the answer is “diversification” or “resilience” or “multi-channel strategy” and add an inspirational quote alongside the ChatGPT -inserted emojis. Telling a Karachi tailor with 14 customers in a WhatsApp group to “diversify their customer-communication stack” does nothing to solve the problem. The infrastructure they depend on was built and made free at the point of use by a corporation that calculated, correctly, that owning that infrastructure was worth more than charging for it. The bill is paid in attention, in advertising, in data, and in the asymmetric power Meta now holds over a substantial fraction of global communication. While the shutdown will (sadly) not happen any time soon, the dependency, however, exists, and the thought experiment is worth running occasionally (with other services as well… looking at you, Google Mail !) because this exact dependency is what should push us to look for alternatives, and not the implausible event that would make it visible. Network effects may be the biggest drivers for this unhealthy dependency, but I believe that each and every person has the ability to make an impact within their families, their friend-circles and their communities, by choosing to use anything but WhatsApp as their main communications channel, ideally a self-hosted alternative . For almost three decades now we’ve had XMPP available to us, with popular and capable implementations like ejabberd , Prosody , and Snikket existing as open-source software that is ready to be used for communications platforms of any size. As a matter of fact, WhatsApp uses XMPP behind the scenes and is in fact built upon the same great technology stack used by ejabberd . For a “lower-level” alternative, there’s the good ol’ IRC that has been around for almost four decades and that is still thriving . Both of these open standards would allow communities, organisations and even whole governments to build public infrastructure that could in large parts replace WhatsApp . PS: Are you a Jabber user already? Come join the community channel !

0 views
annie's blog Yesterday

I have no idea who celebrities are anymore

Julia Roberts? She was in that one movie with that guy, and the other one with the other guy, and like 100 more. Whatever. But she’s old news. Like all the other celebrity names I actually recognize, which isn’t a lot, but is some. Just a minute ago a headline floated by: Person A is doing Thing with Person B, what will Person C think? I have no idea: Who the people are, their relationship or lack thereof, their various claims to fame. I do not possess any crumbs of context helping me interpret the situation or nod knowingly about what C’s thoughts will be. I Got Nothing. Which is fine. Preferable, even. I’ve never been a very good fan, it’s just not my thing. But cultural knowledge always seeps in. You just know some stuff like who’s famous and why, and you even have some sort of opinion about them. Until you don’t. I have reached the don’t point. It’s peaceful here.

0 views
Steve Klabnik Yesterday

Too many words about DIDs

Your “Bluesky account” is not just a Bluesky account: it is an account that can be used with a variety of other applications. This post is going to be an exploration of part of what that means from a technical perspective, so if you’re not a software developer, this post isn’t for you. But what I’m going to explain is the technical mechanism for how your account works separate from Bluesky, and in fact, separate from any particular app. Let’s talk about identity: who are you, anyway? Users of a system need some sort of way to describe who they are to use it. If you want to log in, you need to present who you are. If you want to make a post, well, we need to know who the author of that post is. For atproto, the protocol that underlies Bluesky and other apps in the ATmosphere, they use the “Decentralized Identity” standard, also known as DID. The W3C standardized DIDs in 2022 . As you might guess from the name, DIDs are, an identifier that you can use as the basis of identity for building applications. And the idea is that these identifiers are decentralized. However, a lot of people have a lot of feelings about that specific word, and often accuse atproto of not being properly decentralized. We’re going to go over the details so you can understand how this works, and you can decide for yourself if this approach suits you or not. Here is my DID, we’ll use this as an example: There are three parts, separated by colons: The scheme ( ), the method ( ), and the DID method-specific identifier ( ). To use a DID, such as , you resolve it into a DID Document A set of data describing the DID subject, including mechanisms, such as cryptographic public keys, that the DID subject or a DID delegate can use to authenticate itself and prove its association with the DID. That document contains various properties that describe the identity. Here’s my DID Document, at the time of writing: This document gives you everything you need to know to determine who I am, that is, given an arbitrary post that claims it’s written by me, this document describes how you’d verify that claim. We’ll get into how to do that that in a moment, but first, how do you resolve that DID into that DID document? Well, it’s pretty easy: each method is a standard that describes how you do that. So when you see , that means we use the PLC standard, which we’ll be going over in a moment. Another method supported by Bluesky is . In that case, you wouldn’t use the PLC standard, you’d use the Web one. This is the sense in which DIDs are decentralized: when you present your identity, you get to decide what method validates that that is a real identity. There’s no centralized authority that determines which DID types are valid. Now, of course, that doesn’t mean that every application supports every DID method, because while this specification is very generic, you’re still going to have to write some code to implement that particular method. I could say “Hey I’m ” and unless your app supports the method, it’s not gonna inherently just know what to do. So that is one important caveat. Let’s explain this resolution process for the method. While supported by Bluesky, a very small number of users actually use , but it’s a simpler method and so I think it’s illustrative to go over first. I’ll be using Liz Fong-Jones account as an example here. Her identity for that account is . So how do we resolve this DID into a DID Document? We take the method-specific identifier, which in this case is , and put it into this URL template: You can then go fetch this URL to resolve it into the DID Document, which at the time of writing, looks like this: This is very simple! So why might we not want to use ? Why bother with any other system? Well, this relies on the DNS system. One could make the argument that ultimately, this is still centralized in some form. If Liz’s domain registrar were to take away her domain, she would also lose control of this DID. In a more generic sense, if Liz decides she wants to not use that domain anymore, she will lose control of that identity to whoever does. That could be through non-malicious means, like letting it expire and someone else purchases it, or through malicious ones, like a hack which would compromise her registrar account and take the domain over. Also, you need to have a web server running on that domain with infinite uptime; if the server goes down, so does your ability to get the document. When this DID document changes, there’s no mechanism for clients to know that it’s changed, which means applications may use one that’s out of date, or that there is lag between updating the document and updating the application built on it, which may cause temporary problems until the latest document is fetched. All of these drawbacks led Bluesky to develop their own DID method, which attempts to fix these problems and others. This method is called . To resolve a , you take the entire DID, and put it in this template: You can then fetch that URL and get the DID document. So… what’s the difference? Well, in this case, both nothing and something. In a very literal sense, both are resolved in the same way: you fetch a URL. However, the details matter. There is already two ways in which this is different than DID:Web: I’ve presented the above as pros, but there are also cons. Before, I had to trust the DNS system and domain registrars, now I have to trust plc.directory. All of the same caveats apply in that sense, I have to trust that they don’t take my ID away from me, or that it doesn’t get stolen, etc. However, there are also some important details that mitigate this, which we’ll get to. But for some people, neither trusting DNS nor trusting plc.directory is acceptable, and there are other DID methods that use, for example, a blockchain to resolve the name. Bluesky does not support using any of those DID methods, so for this application, it’s not really relevant, but it’s important to know that they exist. Why do it this way? Well, the simplest way to put it is this: setting up a involves a lot of “nerd stuff.” You have to register a domain, and that’s also an ongoing monetary cost. You have to know how to set up a web server, and author some JSON to put on that server. You have to keep it running. You have to know how to store your private keys, and keep them safe. It’s a non-starter compared to “sign up for this web app.” And Bluesky’s goals involves making this platform accessible to non-nerds. By having plc.directory manage all of this, we eliminate all of those steps. While drafting this post, I have also been made aware of , which expands on and attempts to rectify some of its shortcomings. I have not read the spec yet, but it has reached 1.0, so it is probably worth checking out. I wanted to get this post shipped last week, and didn’t want to delay it further by adding another section, but if I were writing this post in the future, I’d probably want to talk about it as well, so just a little heads-up there. But it does also mean that, in some sense, Bluesky still owns your identity. They’ve generated a keypair for you, and the have access to the secret key. That’s unacceptable for some people. So how do you fix that? Well, has some additional features that does not. For example, will allow you to register additional keypairs with your ID and use them to rotate your signing keys. This allows you to remove the Bluesky generated keys and insert your own. While that is true, it’s also the case that your PDS needs to use your keys to sign your posts. As such, most people are likely to store their keys in their PDS, and so if you are using a Bluesky managed PDS, well, you’ve uploaded your keys to their infrastructure, and that’s probably not acceptable if you’re trying to keep your identity away from Bluesky. Of course, the solution there is to run your own PDS and then rotate your keys. At that point, your key is living on infrastructure you own, and Bluesky has no say over it any more. I think that this possibility is an important design property, and allows motivated users to meaningfully own their identity. A criticism of this boils down to “well, most users won’t do that,” and while that’s true, I also think that’s okay for most people, and that having the choice is more important than forcing every user to deal with their own key management. This is kind of an abrupt end to this post, but I just wanted to get some things down ‘on paper’ as it were. I hope you’ve learned a bit about identity and how it works with atproto. Here’s my post about this post on BlueSky: Too many words about DIDs: steveklabnik.com/writing/too-... Too many words about DIDs Blog post: Too many words about DIDs by Steve Klabnik Your DID is no longer tied to a specific domain name. I can let expire and move to and my stays the same. While a web server still needs to be running, that’s the job of plc.directory, not my own job. This is operationally much simpler.

0 views
DYNOMIGHT Yesterday

Pseudpocalypse

Here’s a conjecture: If you put any significant amount of text on the internet under different names, those identities can be linked using only the text itself. This is possible (I conject) because of the statistical “fingerprint” you leave in everything you write. Imagine a website where you can paste in some brand-new text someone just wrote. In return, the website provides links to all the text that writer has ever published under any name. It’s not perfect, but it’s pretty good. As far as I know, no such website exists—at least not on the public internet. But I suspect it’s possible and will soon become easy. This will pose some difficulty for pseudonymous blogging. Note : I wrote most of this essay in mid-2025, after which I idiotically sat on it for a year tinkering with theorem statements that none of you will read. 1 In the meantime, LLMs have gotten much better at guessing authors from text. (Given the first 1000 words of a draft of this post, Claude 4.8 knows it’s me.) Still, I think we’re just getting started. I expect to see increasingly obscure writers identified from increasingly small bits of text. I expect that this work even when people are writing in a different register or about unrelated subjects. And I expect that everything I’ve ever written under any pseudonym will soon be linked to my genuine-nym. 2 A stronger conjecture is that we’re heading towards a sort of generalized pseudpocalypse. Perhaps, in the future, if you interact with the world through essentially any high-bandwidth channel, then you identify yourself. Say you wear a mask in public and only speak by sub-vocalizing into a voice changer. That’s fine, you’ll still be identified using your body shape, gait, or chemical signature. Or say you don’t like your car being tracked everywhere, so you stop carrying a phone and you somehow convince lawmakers to ban license plates. No problem, your car will still be tracked using tiny scratches or unique pinging sounds from the engine. Or say you don’t like being tracked on the internet, so you lock down your browser profile, buy stuff only with Monero, and connect through a chain of three VPNs. That’s OK. You’ll still be identified through how you wiggle your finger as you scroll down the page. We’re all just too unique, and the information theoretic limit is coming for us. Let’s start from first principles. Imagine that at birth, everyone is assigned a random binary string. Whenever you post anything on the internet, you’re required to sign it with that string. If the strings are very short, like , then lots of other people will have the same one as you. But if the strings are very long, then yours would almost certainly be unique and it would be trivial to link all your pseudonyms. Where’s the transition point? If you only know that the author is currently alive and living somewhere in the Anglosphere, it’s around 29 bits. That’s because if there are K digits, then there are 2ᴷ possible binary strings, and if K = 28.86, then 2ᴷ ≈ 490,000,000 is the number of currently-alive Anglosphere-dwellers. If the strings have fewer than 29 bits, then someone else will probably share your string. If they have more than 29 bits, then your string is probably unique. We don’t (yet?) have to sign the things we write with immutable government-issued strings. But the way you write still provides lots of clues about you by way of your tone, personality, word choice, and so on. Theoretically speaking, I think it has to be possible to link the identities of anyone who writes enough. Imagine again that everyone is assigned a random binary string at birth, but instead of you needing to sign the stuff you write with your string, each time you write a word, there’s some chance that a random bit from your string is revealed and added as a signature to your message. For example, maybe a signature of is added, indicating that your string at position 129 has value 1. Think of your string as representing all your writing style quirks, and a bit being revealed as representing when you write something that reveals a preference. For example, maybe bit 18 indicates if you prefer to write your em-dashes with hideous spaces — like this — or without spaces—like this. If you use an em-dash, that bit is revealed. So imagine you’ve written a lot under Pseudonym A, enough that the full bit-string has been revealed. Maybe it’s this: Now say you start writing under Pseudonym B. Initially, none of the bits will be known: But slowly, you’ll start to leak a few bits: And eventually you’ll leak a lot of bits: Now think about this from the perspective of an “attacker” who wants to know if A and B are the same person. Let’s assume they’ve only seen the above bits, and have no information about anyone else. Then here’s what the attacker knows: Intuitively, if K was 5, then the fact that all bits match wouldn’t prove much, since with 490 million people, lots of people would match on those bits by chance. But if K was 70, it’s extremely unlikely that two different people would share all of them, even with such a gigantic pool to start with. It turns out that if there are N other people with random bits, and you pick K of your bits, the probability that someone exists who matches all of them is 1 - (1-2⁻ᴷ)ᴺ. When N is 490 million, that looks like this: Look at that, 29 appears again. (Isn’t math wonderful?) In general, the transition happens around whatever number of bits K makes 2ᴷ ≈ N, namely K = log₂(N). If you reveal significantly fewer than 29 bits under pseudonym B, then it’s almost guaranteed that there’s someone else out there who matches all of them. But if you reveal significantly more than 29 bits, then there’s almost no chance that anyone else exists who matches all of them. So the attacker essentially knows that A and B are the same person. And I stress again: They know that without needing to see anything from the other 490 million people. Of course, we don’t literally leak bits of immutable feature strings as we write. But you can make the model more realistic, and the same issue persists. If you want to reflect that text only provides noisy information about the writer, then you can add noise to the bits before they’re revealed. If you want to reflect that some writing styles are more common than others, then you can make the distribution over bit strings non-uniform. If you want to reflect that certain quirks are more obvious than others, you can give different bits different probabilities of being revealed. All these make the math more complicated. But they don’t change the basic conclusion: If your writing style contains at least 29 bits of information, and you do enough writing, you’re done. That’s my argument that pseudpocalypse is possible. But I don’t just want to claim that it could happen, eventually. I think it is likely to happen, soon, and that the amount of text you need to reveal isn’t very large. To make that argument, we need to get specific: What features do people have that are reflected in their writing? How many bits of information do those features contain? How accurately can those bits be guessed from written text? Note : To avoid this turning into a giant information theory lecture, I’ll mostly use words like “bit” and “information” without being 100% fully precise about what they mean. I’m doing that because I expect that most people reading this aren’t definition-of-bit fetishists, and anyway being hyper-technical would obscure the big picture. If you’re an information theory enthusiast and/or skeptical that I know what I’m doing, I refer you to the Section For Skeptical Information Theory Enthusiasts, below. Until then, use your intuition and have faith. Say you knew nothing about me other than that I wrote the above words. And say you had to guess my age or religion or occupation. You could guess , right? It wouldn’t be perfect, but you’d do much better than you would without being able to read those words. Thus, somehow, those words contain information about my demographic characteristics. So I tried to make a list of similar things that you could plausibly guess from text at least somewhat better then chance. Here’s what I came up with: In the same spirit, if you only read the above words, could you guess how extroverted or conscientious I am? Again, not perfectly. (When I meet people who read this blog, they usually seem surprised I can survive direct sunlight.) But still, I’m sure you’d do OK. So, again, these words contain information about my personality. What features does personality have? The HEXACO model lists six, namely honesty-humility, emotionality, extraversion, agreeableness, conscientiousness, and openness to experience. I suspect those can all be guessed with reasonable accuracy from a long-enough writing sample. But could you guess more? For each of those six factors, the HEXACO model lists four “facets”. In the abstract, trying to guess 6 × 4 = 24 different personality features from text sounds ludicrous, but just look at them: If you think about specific people, I think you can convince yourself that these 24 represent real things, and that it’s plausible to guess them from text. (Your favorite existential angst + science blogger, for example, might score lower on “modesty” than the other honesty-humility facets.) The different sub-factors are surely correlated, but not perfectly correlated. Of course, the biggest thing you learn from people’s writing is how they write . Do they tend to pointlessly split infinitives? Do they use hyphen-connected words? Do they, incorrectly, position their adverbial clauses? The idea of attributing authorship using writing style features goes back to at least 1440, when Lorenzo Valla demonstrated that the Donation of Constantine —in which Emperor Constantine supposedly donated the Roman Empire to the Catholic Church—used a vernacular that came from 400 years after Constantine’s death and was therefore a forgery. In 1851, Augustus De Morgan observed that average word length tends to be stable for the same author. The first “modern” attempt seemingly came in 1964, when Mosteller and Wallace published Inference in an Authorship Problem : This study [attempts] to solve the authorship question of The Federalist papers; […] Word counts are the variables used for discrimination. Since the topic written about heavily influences the rate with which a word is used, care in selection of words is necessary. The filler words of the language such as an , of , and upon , and, more generally, articles, preposition, and conjunctions provide fairly stable rates, whereas more meaningful words like war , executive , and legislature do not. After an investigation of the distribution of these counts, the authors execute an analysis […] based on Bayesian methods. The conclusions about the authorship problem are that Madison rather than Hamilton wrote all 12 of the disputed papers. Get that? The idea is that your usage of the word war depends mostly on if you happen to be talking about war. But your usage of upon mostly depends mostly on how much you like the word upon . To demonstrate this, they took 48 papers written by Hamilton and 50 by Madison and made this table of how many times they used by , from , and to : Madison liked by . Hamilton was more a to man. Using these kinds of statistics, they concluded that the disputed Federalist papers must have been written by Madison. So I did some research looking for other writing style features that are believed to be stable when people write about different subjects. I found that there are a lot. There were so many that I struggle to even organize them into meaningful groups: Low-level frequencies: Lexical features: Syntactic features: Style features: Rule preference features: Idiosyncratic features: That’s a lot. There are surely more. And these are all “shallow” features that humans came up with using our tiny little brains. I strongly suspect that there are many more “deep” features that could be found by looking for statistical patterns in a sufficiently large dataset. Many of those features might not even have a coherent English-language description. But they’re still there, providing bits for those who seek them. So we leak information about lots of different stuff when we write. But how much information? Is it possible to say how many words are needed to uniquely fingerprint someone? No. To a first approximation, the answer is no. But to a second approximation, maybe? Within an order of magnitude? I’ll try, but it’s going to be hard. How many bits of identifying information does text provide by way of demographic features like age and sex and so on? At first glance, this seems a perilous question, as it depends on the number of categories you consider those things to have. Take sex. For pseudpocalypse purposes, your opinion about how sex should be defined or how many sexes exist is irrelevant. Finer categorizations always provide more information, and our de-pseudonymizing attacker friends will use that information if they can. However, going beyond two categories for sex makes little difference, because the additional categories will be hard to guess and even if you could, categories with low prevalence don’t contribute much extra information. 3 So, for us, two categories is the right answer. And what about age? At first glance, converting age into a set of categories seems meaningless. If you code age by the millisecond, then there are 3.156 trillion categories for people born in the last 100 years. If you code age by the decade, there are only 10. Here, the thing to notice is that while you might be able to guess my decade of birth from how I write, you don’t have a snowball’s chance in hell of guessing the millisecond. (See what I did there? People born in certain decades are more likely to use expressions like snowball’s chance in hell ? 4 ) If we took age to have some crazy number of categories, we’d have to discount later to reflect the difficulty of guessing. My intuition is that it would be hard to guess age more accurately than around five years, so 20 categories seems reasonable. Following this kind of logic, I chose a number of categories for each of the demographic variables, trying to hit the upper end of what could be guessed from text. (I’ll provide the actual categories below.) If each of the age bins were equally likely, then knowing what bin someone fell into would provide 4.32 bits of information, because 2ᴷ ≈ 20 when K = 4.32. Doing that same calculation for each feature gives the maximum amount of information they could contain. But there’s a problem. There are more people aged 30-35 than there are people aged 90-95. So, even if you could guess those age bins perfectly, they’d provide less than 4.32 bits of information on average. However, it turns out that categories need to get pretty damned uneven before information content drops very much. A perfectly balanced 50/50 distribution provides 1 bit of information, but if you switch to a 60/40 distribution, you still get 0.971 bits, and you need to go almost to 90/10 before information content drops to 0.5 bits. 5 The same basic thing is true when there are more than two categories. 6 So I went through all those features, rated them by how unevenly people are distributed, and tried to discount the bits accordingly. I’ve put the full details of what the original categories are and how I discounted them in a footnote. 7 But there’s another problem. Female 65 to 70 year-old Asians living in Scotland tend to have different {occupations, family statuses, religious affiliations} than 15 to 20 year-old Latinos living in Southeast Australia. That is, the above features are correlated. So as you look at more of them, they gradually become less surprising and thus contribute less information. How much less? Answering that the right way would require us to estimate how likely someone is to fall into each of the 20 × 6 × 6 × 2 × 11 × 3 × 3 × 2 × 23 × 3 × 3 × 23 × 3 × 2 = 8,144,737,920 joint categories. That seems hard. But a not-completely-ridiculous approximation is that if a group of variables are all pairwise correlated at a level of ρ>0, then the total information might be reduced by a fraction of ρ. 8 So how correlated are those features? In the social sciences, a correlation of 0.5 is considered quite high. That’s plausible for some pairs of variables, e.g. age vs. health or political leaning vs. religious affiliation. But many of those correlations are are probably quite weak, e.g. age vs. native language or region vs. sex vs. marital status. 9 Overall, my guess is that correlations reduce the total information by at least 10% but I doubt they reduce it by more than 60%. So I’d think the total information in the above features (if you could guess the categories perfectly) is somewhere between 10.6 and 23.9 bits. Let’s take the average and call it 17.2 bits. What about personality features? Let’s use the same same recipe we used for demographic features, but faster: To start, let’s give each of the 24 personality features five bins, in deference to dynomight personality notation . That would correspond to 24 × 2.32 = 55.68 bits total, because 2ᴷ ≈ 5 when K = 2.32. Then we need to discount for correlations. The six main HEXACO personality factors are designed to be uncorrelated, but the different “facets” inside each factor are correlated (usually with a coefficient between 0.3 and 0.6). It seems reasonable to use an overall discount factor of 0.3 to reflect strong intra-factor correlations but weak inter-factor correlations. That suggests 39.0 bits overall. And what about writing style features? How much information do they contain? This seems hard. Some of the features, like character n-grams are actually themselves long lists of features. (Frequency of typing , frequency of typing , etc.) However, many of those features contain little information, since almost everyone types around 0% of the time. And, of course, writing style features are correlated, since people who write instead of are less likely to put spaces around their em-dashes. In absence of a better idea, I’m going to give one bit for each leaf node in the above list of style features. I think of this as giving each feature two bins, and then assuming that uneven distributions of features and correlations (which reduce information) are canceled out by the fact that many features deserve more than one bin and that there are probably more “deep” features that aren’t listed (which increase information). This gives us the suspiciously round number of 50.0 bits. If you believe the above numbers, then we have at least 17.2 + 39.0 + 50.0 = 106.2 bits of identifying information that we leave clues about when we write. That’s a lot. If you could see all those features, it would be enough to identify people even on a planet with 93 million trillion trillion people. But to argue that the pseudpocalypse is nigh, it’s not enough to argue that those bits exist. We need to argue that they can and will be guessed from a relatively small amount of text. So obviously we need to talk about nuclear weapons. In a nuclear detonation, many unstable atoms are created. These spontaneously decay into more-stable atoms, in the process emitting radiation. Some types of atoms are very eager to decay, meaning they release a lot of radiation but stop existing within a few weeks (iodine-131). Others are reluctant to decay, meaning they don’t release as much radiation but they stick around for decades (strontium-90). Others stick around for millions of years, but they produce so little radiation that they’re not a big problem (cesium-135). 10 So, the residual radiation produced after a nuclear detonation is the sum of many different exponential curves, one for each isotope created during the detonation. I suspect that identifying bits in text are sort of like that. Your level of formality and your average sentence length are revealed almost immediately. Your preference for latinate vs. germanic words takes a while to come through. And your social boldness and the fact that you live in Queensland rather than Southeast Australia are revealed very slowly, perhaps so slowly that it’s effectively not revealed at all. Right. So if you start with 106.2 bits, how many of those do you reveal after writing a given number of words? I will answer that question through the noble method of making up numbers. But first, let’s calibrate. You just read 4500 words written by me. How well could you guess my demographic and personality features? As a sanity check, I gave the above words to an LLM and asked it to guess. It did unnervingly well. It wasn’t always right, but it usually was, and it did a great job of rating the confidence of the individual predictions. I don’t think there’s any magical explanation for this. The fact is, if you look at the individual personality and demographic features, guessing them just isn’t that hard. So I’m sure you could do just as well. And given enough time, I’m pretty sure you’d do even better for writing style features. Even so, you’re probably bad at it. Take the example of GeoGuessr , where people guess a location in the world from a random photo. Random people are sort of OK, but if you pick the top natural talents and have them practice obsessively, they’re really good. I don’t think LLMs are particularly good at guessing features from text, either. They weren’t trained for it. It’s just an emergent property of their general intelligence. The information-theoretic limit is surely much higher. So here’s a very rough cut: After 4500 words, I’d think it’s possible to guess around: If we model each of those with a separate exponential, and start them at 17.2 / 39.0 / 50.0 bits, then the total number of identifying bits that remain hidden after writing a given number of words is as plotted here: 11 Et voilà , pseudonymity is compromised when you leak 29 bits, which happens after 1071 words. Of course not. The above figure stands on a creaking tower of tenuous assumptions. I’ve gone through the details of deriving that curve not because you should trust it, but because I think seeing the calculations makes the following points hard to argue with: I’ve made lots of debatable choices in terms of choosing features, assigning numbers of categories, estimating distributions across those categories, discounting for correlations, and guessing how many bins can be guessed. Those choices are all individually suspect. But the above points are supported by a pretty wide margin of error. You can make different choices, but it seems very hard to avoid concluding that the above three points are true. 12 You might be wondering why I’m using so many made-up numbers. After all, there’s a whole field devoted to identifying authors from text, usually called “stylometry” or “authorship attribution”. They have research papers and competitions and all that. However, as best I can tell, state of the art published results look something like this: That sounds OK, but that’s only identifying people against a pool of ~50 authors. For my claim to be true, similar accuracy would have to be possible with 490 million people. That’s seven orders of magnitude more. The thing is, the methods those papers are using are extremely weak. All the above math assumes that you’re operating at the “information-theoretic limit”, making perfect use of all available information. If you want to get close to that, we now have some idea how to do it: You apply the “modern” machine learning recipe of gigantic dataset + gigantic neural network + gigantic fortune spent on GPUs. My guess is that for us, that would require something on the order of “all the words ever written” + “tens of billions of parameters” + “tens of millions of dollars”. I couldn’t find a single paper that came remotely close to attempting that. So I don’t think those papers tell us much, for the same reason that a 3rd-order Markov model trained on a few books doesn’t tell us much about how good computers could be at writing text. LLMs have shown that if you use the above recipe, then computers can get close to the information-theoretic limit for generating text. 13 So, I suspect that an LLM-level effort could achieve the same thing for identifying authors. You might also wonder: Why am I talking about this as some possible future technology? Isn’t that technology just LLMs? I suspect the technology will be quite LLM-like in how it models human language. But current general-purpose LLMs aren’t trained for this task. They’re good at it “by accident”. So, just like specialized chess AIs can crush LLMs at chess, I suspect specialized stylometry methods could crush general-purpose LLMs at stylometry. It’s just that those specialized stylometry methods don’t seem to exist yet, or at least aren’t public. 14 So we shouldn’t imagine that current LLMs are anything close to what’s possible, even if you assume that generic LLM progress stopped today. 15 If this is all true, what could be done about it? The most obvious “countermeasure” would be to get used to it. I mean, imagine that we did live in a world in which everyone literally had to sign everything they wrote with a unique immutable string. What would happen? I’d expect a mixture of: There are strong historical analogies here, since over the past 20 years many governments and tech companies have in fact decreed that people must sign the things they write with their real names. The effects seem to vary quite a lot based on the ambient culture and political system. Overall, my impression is that people are already much more comfortable with the idea that their work colleagues might read their dating profile or learn that they go to furry conventions. I’m optimistic that culture will continue to adapt to respect the fact that we all encompass multitudes. This seems healthy. Some effects seem clearly positive. Self-censoring is not necessarily bad. For example, on the margin, real-names surely stop some teenagers from engaging in cyber-bullying. On the other hand, were you ever a teenager? I’m pretty sure that for anyone who is “different”, having those differences broadcast to the world creates a much larger “bullying surface area”. So the effects are mixed. And adults aren’t as different from teenagers as we might like to think. Twenty years ago, I might have predicted that real names would discourage people from expressing controversial political ideas online. Superficially, that seems completely wrong. At least in the West, lots of people are very happy to express minority political views, and if you disagree at all, then you can go to hell. But I also tend to think this hides a lot of self-censorship, where most people don’t want engage in political mortal combat and so are cowed by a feisty minority. And, obviously, people in certain countries know that it’s unwise to criticize the Party. So, getting used to it seems like an imperfect solution at best. Another countermeasure would be to not build this technology, or not make it widely available. In the short term, this seems plausible. As far as I can tell, it’s been possible for years for a modestly-funded group to build a phone app that would identify most people on the street from a photo. And yet, almost no one reading this has access to such an app. If general-purpose LLMs continue to get better at stylometry, it seems entirely possible that AI companies might decide it’s a safety issue and train their AIs to refuse to do it. 16 This could work for a while. But if the technology is possible, it seems certain that governments will build it and use it. They might try to keep it out of the hands of normal people. Certain governments might restrict their own use. My privacy-minded allies always seem very jaded, but it wouldn’t surprise me at all if the Supreme Court declared that a warrant was needed before the FBI could de-pseudonymize a U.S. citizen. But when/if that technology becomes sufficiently cheap, it seems like it would be very difficult to keep it out of the hands of normal people and/or bad actors. My guess is that it’s possible to create a program that’s a few hundred gigabytes large and can run (slowly) on most modern laptops. If that program is made public, it would be hard to put the genie back in the bottle. There are also technological countermeasures. Most obviously, you could run your writing through a “filter” to try to remove identifying bits, e.g. by asking an LLM to rewrite it. It’s hard to be sure how well this would work, since we don’t have accurate estimates of how many bits you’re starting with or how many bits this would remove. But I’d guess this would be pretty effective if done carefully. The reason is that the number of identifying bits you leave in writing probably isn’t that large, relative to the number needed to identify you. If you “homogenize” your writing to remove all style and personality, you should be able to remove most of those bits. Theoretically, you’ll still leak some information. But I’d think this would substantially increase the amount you could write while remaining pseudonymous. 17 But after thinking about it, this makes me sad. Effectively, this countermeasure would preserve pseudonymity by taking writing and destroying all traces of humanity. It seems like this would work well for the “bad” uses of pseudonymity, like cyber-bullying or coordinated violence, but it wouldn’t work at all for the “good” uses, like for example someone who likes to write pseudonymously because they feel like it allows them to be more honest and vulnerable and more fully themselves, damn it. Maybe this isn’t just true for writing. Maybe it’s just a feature of our universe that if you interact with the world in any significant way, then you leave traces that make it possible to identify you. If you walk around in public, then you can likely be identified by your face, your gait, your voice, your DNA, your retinas, or your literal fingerprints. Or say you use the internet. Even if you lock down your browser fingerprint and hide your IP address using a VPN or Tor, a sufficiently powerful adversary could still identify you by analyzing global packet flow. Or say you use any phone or computer. You might be identified through keystroke dynamics or the way you jiggle your finger or mouse. Say you buy food at the grocery store, but you pay with cash and somehow shop at a grocery store with no cameras. If you buy more than a handful of items, I’d bet you can still be identified through the patterns in the stuff you buy. (Incidentally, did you ever notice that cash has serial numbers on it? And did you know that more and more ATMs are starting to track those numbers?) Or say you don’t like your car being tracked, so you stop carrying a phone and somehow get lawmakers to outlaw license plates. Still, your car surely has a few small unique scratches, and the engine probably doesn’t sound exactly the same as other cars, even from the same model and year. So if there’s any high-resolution video or audio, that’s still enough to track you. Say you plug your headphones into a charging station at the airport. Your headphones have eccentricities in their analog charging circuits. If someone really wanted to, they could track that. Or say you use electricity. Given high-resolution power-usage data, what can be said about how many people live with you? And what devices you’re using? Probably a lot? Or say you use a toilet. Many places already test sewage and know, at a population level, what drugs people are using and how prevalent various diseases are. Imagine this was upgraded to test many places in the system, with high temporal resolution, possibly correlated with flow measurements from individual houses. That would be exciting. Or say you are a country and you have submarines. Can they be detected by adversaries using distributed acoustic sensing? What about satellite-based synthetic aperture radar? Gravity Gradiometers? Quantum magnetometry? As far as I can tell, the general trend is that without countermeasures, almost everything can be identified. Countermeasures can make it harder, but they’re costly, and on the whole, the arms race seems to favor the identifier, not the person who doesn’t want to be identified. I stress: This is not all bad. The goodness / badness of a generalized pseudpocalypse depends on how society is structured. After all, the foundation of civilization is finding ways for people to make deals, and arguably less privacy makes that easier. The degree that we live in a vulnerable world where it’s easy to create civilization-destroying technologies, perhaps we’re very lucky to find ourselves in a non-private world. Still, I do worry that privacy has long provided a kind of “slack” from laws and norms. Historically, that slack has limited the power of institutions to enforce their rules. If privacy is going away, we need to think about how to preserve slack, particularly when institutions don’t want to. Above, I tried to estimate the number of bits of identifying information in writing. But what is a “bit”? In general, if x is a discrete random variable, then the Shannon entropy of x in bits is H(x) = ∑ₓ p(x) log₂(1/p(x)) , where the sum is over all the values x can take. This is always bounded between zero and the logarithm of the number of values x can take. That’s fine, but “writing style” is not a discrete variable with a discrete number of categories. So how can I estimate the entropy of writing style? The short answer is that I can’t. What I’ve actually estimated above is the mutual information between writing and writing style. Let s be a random variable representing writing style. Think of this as some sort of high dimensional continuous vector representing all the quirks of how different people write. And let x be a writing sample of some length. This is discrete because we can represent writing on digital computers. Then what I’ve estimated above is the mutual information I(x;s) = H(x) - H(x|s) , where H(x|s) is the conditional entropy of x given s . This can be measured in bits because both H(x) and H(x|s) can be measured in bits. So that’s what my estimate above really says: I(x;s) ≈ 106.2 bits . Now, you still might be skeptical. Above, I’ve implicitly assumed something like the following was true: It’s possible to identify one person out of N possibilities with low accuracy if and only if the mutual information between identifying features and writing is at least log₂(N) bits. That’s how I justified pseudonymity being compromised around 29 bits. But is it really true? Strictly speaking, no. Actually, even more strictly speaking, it’s “not even untrue” because it’s not precise enough to be true or false. But as far as I can tell, basically any precise version of that statement is false. However, it’s possible to find versions of that statement that are true, provided you add some extra not-too-crazy assumptions. To start, let’s consider an extremely simple model of information leakage. Theorem. Suppose the world consists of you plus N other people, and suppose each person has a binary identity string, drawn at uniform from the distribution over M -bit binary strings. All these strings are known to the attacker. Suppose you pick some subset of K bits and reveal them. Then the probability that this identifies you is Furthermore, in order to hold the probability of being identified below (1-1/N)ᴺ ≈ exp(-1) ≈ 36.7% , it is necessary that K ≤ log₂(N) . Proof. The probability that all K observed features collide with any random person in the crowd is 2⁻ᴷ . Thus, the probability of no collisions after checking the crowd of N people (meaning you are the only one matching the observed features) is (1-2⁻ᴷ)ᴺ . □ That’s simple. But it’s not realistic at all, since it assumes that people have immutable binary strings that they leak into their writing. Can we make it more realistic? Well, there is a simple lower bound. That is, we can say in general that if the mutual information is significantly less than log₂(N) , then it’s not possible to reliably identify someone. Theorem. Suppose N random people are selected and their full writing style features are made public. One person from that group is chosen and produces a writing sample. Then, the attacker must guess who produced it. The average success rate of the attacker (averaged over the random pool, the random choice of author, and the random writing sample) is at most (I(x;s)+1)/log₂(N) . Proof. Let S=(s₁, s₂, s₃, …) be the pool of N styles and let n be a random variable indicating which person was chosen. Fano’s inequality says that the highest possible success rate is bounded by the conditional mutual information between the writing sample x and the identity n , conditioning on the pool of writing styles, i.e. the probability of success is at most (I(x;n|S)+1)/log₂(N) . However, we can bound that conditional mutual information as I(x;n|S) ≤ I(x;n,S) = I(x;n,sₙ) = I(x;sₙ) = I(x;s). The first inequality is standard. The second step uses the fact that given n , the writing x is conditionally independent of all styles except the chosen writer. The third step uses the fact that n is conditionally independent of x given sₙ . The last step uses that (x,sₙ) is distributed as (x,s) . Substituting this bound gives the claimed result. □ So, if mutual information is much less than log₂(N) , reliable identification is impossible, even if the attacker knows all the style vectors perfectly. So, provided you don’t leak that many bits, you’re definitely safe. But is the converse true? Does leaking more than log₂(N) bits always identify you? The general answer is no . The basic problem is that I(x;s) is the average information that an average person leaks in an average writing sample. Without further assumptions, you can construct scenarios where some rare people and writing samples contain gigantic amounts of information, but most people usually leak nothing. That would mean that the attacker is very certain in some cases but usually learns nothing. So, to get a guarantee that identification is actually possible, you need to make some kind of additional assumption that the information leakage rate doesn’t vary too much between different writers or between different things they write. Suppose that p(x,s) is the joint distribution over writing styles s and writing samples x . Let’s suppose that the attacker knows the true style vector ŝ for some person. Then, they will be given a writing sample x that either came from that person or came from a randomly chosen person, and must decide which. Formally, the attacker’s goal is to guess if x was sampled from the writing distribution for that person, p(x|ŝ) or from the population marginal p(x) . Intuition suggests that the attacker’s best strategy will be to look at the ratio p(x|ŝ)/p(x), and “accept” x as coming from ŝ if above some threshold, and reject it otherwise. In fact, the Neyman-Pearson lemma guarantees that this is the optimal strategy, in a very strong sense: That ratio contains all the information that’s useful for making that decision. Now here’s something interesting: Instead of looking at the ratio, the attacker could look at the logarithm of the ratio. It makes no difference since it’s monotonic. But if you take the logarithm of that ratio, and take the expectation over people and over texts, what do you get? Well: 𝔼 ln (p(x|s)/p(x)) = 𝔼 ln (p(x,s)/(p(x) p(s))) = I(x;s) It’s the mutual information! So, intuitively, the mutual information is how much an attacker learns about the style of the writer “on average”, where that average is over both writers and text. The following theorem will look at the average information in text for a writer with a particular style. I’ll define this as D(s) = KL(p(X|s) || p(X)) . Intuitively, this is how different the writing of someone with style s is from the population average. That’s because if you take the average of this value over different styles, you get the mutual information. That is, I(x;s) = 𝔼[D(s)] . 18 Theorem (informal). Suppose that the attacker will observe some text and wishes to classify it as either coming from a writer with specific known style ŝ , or coming from someone with a random style. Suppose that the attacker is only willing to tolerate some small risk ε of a false positive. Provided that D(ŝ) is significantly larger than -ln(ε) , the attacker can achieve that, while also keeping the risk of false negatives very low, provided that the variance of how much information is revealed in a random writing sample is bounded. Theorem. Let D(ŝ) = KL(p(X|ŝ) || p(X)) to be the divergence between the target’s writing distribution and the marginal distribution. Also, define qₜ(x) ∝ p(x|ŝ)ᵗ p(x)¹⁻ᵗ to be the family that interpolates between those two distributions. To formalize the idea that “information leakage” for ŝ doesn’t vary that much, we assume that some constant V exists such that for 0 < t < 1 , the variance of log(p(x|ŝ)/p(x)) under qₜ is bounded by V . Then for any ε satisfying exp(-D) < ε < exp(-D + ½ V) , it is possible for the attacker to simultaneously achieve a false positive rate of FPR ≤ ε and a false negative rate of FNR ≤ exp( - ½ (D+ ln ε)² / V). This false positive rate reflects the mistake rate provided the writing sample x came from a randomly chosen other person, while the false negative rate reflects the mistake rate provided the writing sample x actually came from the person with style ŝ . Proof sketch. Let f be the distribution of l(x) = log(p(x|ŝ)/p(x)) with respect to p(x|ŝ) and let g be the distribution of l(x) with respect to p(x) . The stated variance assumption implies a quadratic bound K(u) ≤ D u +½ V u^2 for -1 < u < 0 , where K is the cumulant generating function of f . Observe that g is an exponential tilting of f . The attacker’s strategy must be to “accept” x as coming from ŝ if l is above some threshold c and “reject” it otherwise. Use K in a Chernoff bound on the probability l is less than c under f to upper-bound FNR ≤ exp( - ½ (D-c)²/V) . Now, using that g(l) = exp(-l) f(l) , again use K in a Chernoff bound on the probability l exceeds c under g to upper-bound FPR ≤ exp( -c - ½ (D-c)²/V) . Both of these bounds are simultaneously valid when D-V < c < D . Setting c to make the false-positive bound equal to ε gives FPR ≤ ε and FNR ≤ exp( -½ (V - √(V² - 2V(D + ln ε)))²/V). The latter can be relaxed into the stated result using that √(1-x) ≤1-x/2 for 0 ≤ x ≤ 1 . □ Now, if we suppose that the attacker wants to find a particular person, with a particular known style s . And suppose that the attacker has a pool of N people and will see one writing sample from each, but wants to limit the total probability of a false positive to δ after seeing one sample from each person. Then, they will need that (1-ε)ᴺ ≈ exp(-εN) = (1-δ), which is satisfied by ε ≈ δ/N . Substituting this into the previous result says that the attacker can hold the total risk of a false positive to δ while achieving a false-negative risk of FNR ≤ exp( - ½ (D(s) + ln δ - ln N)² / V). These results use natural logarithms because the math is easier if you measure information in nats. If you measure information in bits then you would get log₂ δ and log₂ N . (Rescaling D and V appropriately.) So, again, as long as the average information for user s is significantly larger than log₂ N , the attacker can identify that user with minimal risk of false positives. Some writers might leak more information (higher D(s) ) and some writers might leak less information (lower D(s) ). But remember, I(x;s)=𝔼 D(s) . So as long as information leakage doesn’t vary too much between people, and assuming that I(x;s) is much larger than log₂ N (and assuming that variance condition), almost everyone can be identified. Editor’s note: After this sentence was written, many additional hours were devoted to further idiotic tinkering.  ↩ It’s fine.  ↩ A standard binary variable that is 0 or 1 with 50% probability conveys 1 bit of information, while a variable that is 0 / 1 / 2 with probability 49.8% / 49.8% / 0.4% conveys 1.0336 bits.  ↩ People born in certain decades are also presumably more likely to employ see what I did there gambits.  ↩ For example, here is the information content for seven different “bent coins”: Here’s a more formal looking version of the table from the previous footnote: You can generate that table by running this code: With three categories, the story is much the same. Things need to get quite uneven before information drops too much: You can generate that with this code: Roughly speaking, we we should discount those maximum bits as follows: The Shannon entropy of a categorical distribution is - Σᵢ pᵢ log₂ pᵢ. Or, in python: Age: It’s hard for me to imagine you could guess age from text with accuracy higher than 5 years. If you assume an age between 0 and 100, that would be 20 categories and log2(20)=4.32 bits. These are mildly non-uniform so I’ll reduce to 3.9. Education: I’m assuming 6 categories: less than high school, high school, some college, finished college, master’s degree, doctorate. That would be log2(6)=2.58 bits, but fairly uneven, so I’ll reduce by 20% to reflect that. Ethnicity: Assuming 62% white, 11% black, 16% latino, 6% asian, 1.5% indigenous, 3.5% mixed/other, and actually using the entropy formula. Family status: I’m using two categories: Children / no children, on the logic that guessing the number of children would be very hard. These are mildly non-uniform, so I’ll drop to 0.8 bits. You could have a third category for having children that are grown and that had left home, but this would be heavily redundant with age. Income: The US census gives 11 income brackets. That seems as good a way of discretizing as anything. That would be log2(11) = 3.459 bits, but these are again moderately non-uniform, so I’ll reduce to 2.5. Marital status: I’m taking 3 categories (single, married, divorced / widowed / etc). That would be log2(3)=1.58 bits at maximum, but again these are somewhat non-uniform, so I dropped that to 1.2. Mental health: I’m using 3 categories: “Healthy”, “chronic condition”, and “severe issues”. Assuming 73% healthy 25% chronic condition, 2% “severe issues”, and using the entropy formula gives 0.9 bits. Native language: I’m using 2 categories, namely “English native”, and “non-English native”. These are pretty uneven inside the Anglosphere, so I’ll drop from 1 bit to 0.6 bits. Occupation. The BLS classification gives 23 major groups. That would be log2(23)=4.523 bits, but it’s moderately non-uniform, so I’ll reduce to 4 bits. Physical health: Assuming 60% “healthy” 30% “chronic condition” 10% “severe issues” and using the entropy formula. Political leanings: I’m using three categories (left, center, right). These are fairly uniform so I’m using 1.58 bits. Region: I asked an LLM to divide the Anglosphere up into a number of regions with reasonable granularity. With some tinkering, it gave 23 regions: South East England, South West England, Midlands, Northern England, Scotland, Wales, Republic of Ireland, Northern Ireland, Quebec, Ontario, Western Canada, Atlantic Canada, Northeast US, Southern US, Midwest US, Western US, Alaska, Hawaii, Southeast Australia, Western Australia, Queensland, Central & Southern Australia, New Zealand. With LLM-generated population estimates (which looked reasonable) and plugging into the entropy formula, this gave 3.5481 bits. Religious affiliation: 3 categories (christian, other religion, atheist / agnostic). These are uniform-ish. Sex: 2 categories, near-even  ↩ Consider a set of binary random variables, each of which is equally likely to be 0 and 1, yet all are correlated with a pairwise correlation coefficient of ρ. There are many distributions that satisfy this condition, but a natural choice is an Ising model. If there are many variables, then the entropy per-variable in an Ising model with pairwise correlations of ρ tends to h((1+√ρ)/2), where h is the binary entropy function . We can print out those numbers: As you can see, the entropy per-variable is always a bit more than 1-ρ. But the Ising model is optimistic, in the sense that it has the highest entropy of all distributions meeting the given conditions. So, screw it, let’s estimate the entropy per-variable to just be 1-ρ.  ↩ If it means anything to you, I asked Kimi 2.6 to hallucinate some numbers: Personally, this doesn’t mean very much to me…  ↩ It’s more complicated than this, because some atoms (e.g. strontium-90) emit more energy per decay than others. And some types of radiation are more harmful to human life than others.  ↩ In general, if you want an exponential curve f(n) that starts at 1 for n=0 and decays to 1-X for n=N, you should choose f(n) = exp(n × ln(1-X) / N). So for demographic features we’re using X=0.6 and N = 4500, meaning f(n) = exp(-0.00020362 × n). For personality features, we’re using X=0.7, meaning f(n) = exp(-0.00026755 × n), and for writing style features, we’re using X = 0.8, meaning f(n) = exp(-0.000357653 × n). So the total number of bits remaining hidden is 17.2 × exp(-0.00020362 × n) + 39.0 × exp(-0.00026755 × n) + 50.0 × exp(-0.000357653 × n).  ↩ OK, what’s the most likely reason I might be wrong? Above, I used math to estimate the information in features, and then I basically made up numbers for how much of that information can be guessed from text. Even so, my greatest concern is that the first part. I’m a bit worried that I might be overestimating the amount of information in the features themselves due to inadequately discounting for correlations. For one thing, there are probably correlations between feature groups. (For example, I’d bet that people who are high in perfectionism are less likely to use lose and loose interchangeably, and that people who live in Northern England are more likely to use the character string than people who live in Hawaii.) Also, my crude method of discounting information by ρ due to pairwise correlations of ρ might not discount enough: I used an estimate based on an Ising model, which is the maximum-entropy (highest information) distribution given the correlation constraints. I haven’t been able to figure out how much lower the information could be in the worst-case.  ↩ People debate if this is true for “intelligence”, but it’s definitely true in terms of bit-rate.  ↩ Also, arguably, stylometry is about language. This means that large language models probably have much of what they need baked in. That might explain why they’re pretty good at it just “by accident”. But to do this optimally I think they’d need self-reflection (e.g. access to probabilities of text given different contexts) that current LLMs aren’t typically capable of, and wouldn’t know how to manipulate correctly without task-specific training.  ↩ You could conjecture that near-optimal stylometry abilities are some kind of “emergent property”. But the general lesson so far is that LLMs mostly don’t have emergent properties but are just good at what they’re trained at.  ↩ (Meta-joke about you—person who works at an AI company—thinking, “maybe we should do that”, coming to this footnote, and seeing this meta-joke.)  ↩ Instead of “homogenizing” writing by imposing a generic style, perhaps it would be better to “camouflage” it by enforcing a very strong but random style.  ↩ Be a little careful here: Typically, the KL-divergence is understood to be measured in nats. But in this article, I’ve measured mutual information in bits. That’s fine, but you need to convert. For example, 106.2 bits = 73.60 nats.  ↩ A and B have revealed K overlapping bits, which all match. Different people have a 50% chance of matching on any given revealed bit. Non-different people have a 100% chance of matching on any given revealed bit. There are 490,000,000 people. Family status Marital status Mental health Native language Physical health Political leanings Religious affiliation Honesty-humility Sincerity Greed avoidance Emotionality Fearfulness Sentimentality Extraversion Social self-esteem Social boldness Sociability Agreeableness Forgivingness Flexibility Conscientiousness Organization Perfectionism Openness to experience Aesthetic appreciation Inquisitiveness Unconventionality Word lengths Sentence lengths Paragraph lengths Punctuation frequencies (commas, colons, dashes, parentheses) Function word frequencies ( the , of , and , to ) Adverb frequencies Intensifiers ( very , really , quite , pretty , so ) Evidential markers ( apparently , evidently , obviously ) Downtoners ( somewhat , fairly , rather ) Pronoun usage Overall preferences ( I / we vs. you vs. he / she / they ) Third-person singular preferences ( he , she , he or she , they , one ) Modal verbs ( can , could , might , must , should , will , would ) Hedges ( perhaps , maybe , possibly , probably ) Conjunctions ( and , but , yet , so ) Known stable ratios ( the / a , this / that , these / those , I / me / my ) Character N-grams (3-grams and 4-grams) Word N-grams (often 3-grams) Vocabulary size Lexical diversity / type-token ratio (Number of distinct words divided by number of words.) Frequencies of rare words Semantic density Discourse marker positions, combinations ( So , anyway , so anyway ) Use of abbreviations and acronyms Preference for latinate vs. germanic words ( The majestic creature traversed the terrain vs. the mighty beast strode across the land .) Syntactic complexity Subordination index Average parse tree depth Use of passive voice. Nominalization ( She was shocked I ate the pizza vs. My pizza consumption shocked her ) Verb tense and aspect ( I walk vs I walked vs I was walking vs I have walked ) Sentence structure preferences: Branching preferences (Cursed everyone had a good time when Alice taught some cool dogs I met and brought to dinner to juggle vs. clumsy-but-readable I met some dogs and they were cool and I took them to dinner and Alice taught them to juggle and and everyone had a good time .) Adverbial clause positioning ( Suddenly I was hungry vs. I was, suddenly, hungry vs. I was hungry, suddenly ) Sentence-final weight ( Your plan won’t work because of the dyslexic bears vs. Dyslexic bears mean your plan won’t work. ) Polysyndeton ( I like dogs, cats, and ferrets vs. I like dogs and cats and ferrets .) Repetition / breaking of syntactic structures. Register / formality. Patterns in sentence length (long/short/long/short vs. long/long/short/short) Stressed syllable interval preferences (e.g. iambic vs. trochaic) Minor punctuation ( I laughed—you cried vs. I laughed — you cried , “…” (three periods) vs. “…” an actual ellipsis) Capitalization. (Job titles, seasons, after a colon, mistakes) Apostrophes ( Steve Jobs’ car vs Steve Jobs’s car , 1990’s vs 1990s ) Hyphenation ( a highly-stable feature vs a highly stable feature ) Oxford commas. Article omissions ( Local dog was petted. vs. A local dog was petted. ) Relative pronoun omissions ( the dog you petted vs. the dog that you petted ) Who vs. whom . Split infinitives ( To obsessively blog vs. to blog obsessively ) Whitespace habits. Spelling errors ( loose instead of lose ) Grammar errors. ( Between you and I ) Consistent, unique typos Other consistent errors (repeated words, un-closed parentheses) 60% of the demographic features 70% of the personality features 80% writing style features You have far more than 29 bits of identifying information that you leak into your writing. Some of those bits take a long time to get revealed, but others are revealed pretty quickly. There are enough “fast leaking bits” that you can be identified from a writing sample that’s “pretty small”. Take 50 people. Get a few hundred writing samples from each author, each 1000-2000 words long. Now, take a new writing sample from one of those authors. Do some standard machine learning stuff. Hey look, the author can be identified with ~95% accuracy! People become more comfortable with their “full selves” being public, with less compartmentalization. People pull back from communicating in public channels, relying more on group chats and the like. People self-censor. If you walk around in public, then you can likely be identified by your face, your gait, your voice, your DNA, your retinas, or your literal fingerprints. Or say you use the internet. Even if you lock down your browser fingerprint and hide your IP address using a VPN or Tor, a sufficiently powerful adversary could still identify you by analyzing global packet flow. Or say you use any phone or computer. You might be identified through keystroke dynamics or the way you jiggle your finger or mouse. Say you buy food at the grocery store, but you pay with cash and somehow shop at a grocery store with no cameras. If you buy more than a handful of items, I’d bet you can still be identified through the patterns in the stuff you buy. (Incidentally, did you ever notice that cash has serial numbers on it? And did you know that more and more ATMs are starting to track those numbers?) Or say you don’t like your car being tracked, so you stop carrying a phone and somehow get lawmakers to outlaw license plates. Still, your car surely has a few small unique scratches, and the engine probably doesn’t sound exactly the same as other cars, even from the same model and year. So if there’s any high-resolution video or audio, that’s still enough to track you. Say you plug your headphones into a charging station at the airport. Your headphones have eccentricities in their analog charging circuits. If someone really wanted to, they could track that. Or say you use electricity. Given high-resolution power-usage data, what can be said about how many people live with you? And what devices you’re using? Probably a lot? Or say you use a toilet. Many places already test sewage and know, at a population level, what drugs people are using and how prevalent various diseases are. Imagine this was upgraded to test many places in the system, with high temporal resolution, possibly correlated with flow measurements from individual houses. That would be exciting. Or say you are a country and you have submarines. Can they be detected by adversaries using distributed acoustic sensing? What about satellite-based synthetic aperture radar? Gravity Gradiometers? Quantum magnetometry? Editor’s note: After this sentence was written, many additional hours were devoted to further idiotic tinkering.  ↩ It’s fine.  ↩ A standard binary variable that is 0 or 1 with 50% probability conveys 1 bit of information, while a variable that is 0 / 1 / 2 with probability 49.8% / 49.8% / 0.4% conveys 1.0336 bits.  ↩ People born in certain decades are also presumably more likely to employ see what I did there gambits.  ↩ For example, here is the information content for seven different “bent coins”: Probability of landing heads Information 0.50 (fair coin) 1.000 0.60 0.971 0.70 0.881 0.80 0.722 0.90 0.469 0.95 0.286 0.99 0.081 ↩ Here’s a more formal looking version of the table from the previous footnote: p(A) p(B) Information 0.50 0.50 1.000 0.60 0.40 0.971 0.70 0.30 0.881 0.80 0.20 0.722 0.90 0.10 0.469 0.95 0.05 0.286 0.99 0.01 0.081 You can generate that table by running this code: With three categories, the story is much the same. Things need to get quite uneven before information drops too much: p(A) p(B) p(C) Entropy 0.333 0.333 0.333 1.585 0.400 0.300 0.300 1.571 0.500 0.250 0.250 1.500 0.600 0.200 0.200 1.371 0.700 0.150 0.150 1.181 0.800 0.100 0.100 0.922 0.900 0.050 0.050 0.569 0.950 0.025 0.025 0.336 0.990 0.005 0.005 0.091 You can generate that with this code: ↩ Roughly speaking, we we should discount those maximum bits as follows: Near even: No discount. “Mildly uneven” (E.g. 70/30 with two categories) Discount by 10%. “Quite uneven” (E.g. 90/10 with two categories) Discount by 50%. “Extremely uneven” (E.g. 99/1 with two categories) Discount by 90%. Consider a set of binary random variables, each of which is equally likely to be 0 and 1, yet all are correlated with a pairwise correlation coefficient of ρ. There are many distributions that satisfy this condition, but a natural choice is an Ising model. If there are many variables, then the entropy per-variable in an Ising model with pairwise correlations of ρ tends to h((1+√ρ)/2), where h is the binary entropy function . We can print out those numbers: ρ h((1+√ρ)/2) 0.0000 1.00000000 0.1000 0.92661216 0.2000 0.85048963 0.3000 0.77121926 0.4000 0.68826012 0.5000 0.60087604 0.6000 0.50801160 0.7000 0.40803633 0.8000 0.29811751 0.9000 0.17212786 1.0000 0.00000000 As you can see, the entropy per-variable is always a bit more than 1-ρ. But the Ising model is optimistic, in the sense that it has the highest entropy of all distributions meeting the given conditions. So, screw it, let’s estimate the entropy per-variable to just be 1-ρ.  ↩ If it means anything to you, I asked Kimi 2.6 to hallucinate some numbers:   Age Edu Eth Fam Inc Mar Mhe Nlg Occ Phe Pol Reg Rel Sex Age 1.0 -0.2 0.0 0.6 0.1 0.5 -0.1 0.0 0.2 -0.5 0.1 0.0 0.2 -0.1 Edu -0.2 1.0 0.3 0.2 0.6 0.2 0.1 0.1 0.7 0.3 0.3 0.2 -0.2 -0.1 Eth 0.0 0.3 1.0 0.2 0.3 0.1 -0.1 0.7 0.3 -0.3 0.2 0.4 0.4 0.0 Fam 0.6 0.2 0.2 1.0 0.2 0.7 -0.1 0.0 0.1 0.0 0.1 0.0 0.2 0.1 Inc 0.1 0.6 0.3 0.2 1.0 0.3 -0.2 0.1 0.7 0.3 0.1 0.2 0.0 -0.1 Mar 0.5 0.2 0.1 0.7 0.3 1.0 0.2 0.0 0.1 0.2 0.1 0.0 0.2 0.0 Mhe -0.1 0.1 -0.1 -0.1 -0.2 0.2 1.0 0.0 -0.2 0.4 0.0 0.0 -0.1 0.1 Nlg 0.0 0.1 0.7 0.0 0.1 0.0 0.0 1.0 0.1 0.0 0.1 0.5 0.3 0.0 Occ 0.2 0.7 0.3 0.1 0.7 0.1 -0.2 0.1 1.0 0.1 0.2 0.2 0.0 0.3 Phe -0.5 0.3 -0.3 0.0 0.3 0.2 0.4 0.0 0.1 1.0 0.0 0.1 0.0 0.1 Pol 0.1 0.3 0.2 0.1 0.1 0.1 0.0 0.1 0.2 0.0 1.0 0.5 0.4 0.1 Reg 0.0 0.2 0.4 0.0 0.2 0.0 0.0 0.5 0.2 0.1 0.5 1.0 0.2 0.0 Rel 0.2 -0.2 0.4 0.2 0.0 0.2 -0.1 0.3 0.0 0.0 0.4 0.2 1.0 0.1 Sex -0.1 -0.1 0.0 0.1 -0.1 0.0 0.1 0.0 0.3 0.1 0.1 0.0 0.1 1.0 Personally, this doesn’t mean very much to me…  ↩ It’s more complicated than this, because some atoms (e.g. strontium-90) emit more energy per decay than others. And some types of radiation are more harmful to human life than others.  ↩ In general, if you want an exponential curve f(n) that starts at 1 for n=0 and decays to 1-X for n=N, you should choose f(n) = exp(n × ln(1-X) / N). So for demographic features we’re using X=0.6 and N = 4500, meaning f(n) = exp(-0.00020362 × n). For personality features, we’re using X=0.7, meaning f(n) = exp(-0.00026755 × n), and for writing style features, we’re using X = 0.8, meaning f(n) = exp(-0.000357653 × n). So the total number of bits remaining hidden is 17.2 × exp(-0.00020362 × n) + 39.0 × exp(-0.00026755 × n) + 50.0 × exp(-0.000357653 × n).  ↩ OK, what’s the most likely reason I might be wrong? Above, I used math to estimate the information in features, and then I basically made up numbers for how much of that information can be guessed from text. Even so, my greatest concern is that the first part. I’m a bit worried that I might be overestimating the amount of information in the features themselves due to inadequately discounting for correlations. For one thing, there are probably correlations between feature groups. (For example, I’d bet that people who are high in perfectionism are less likely to use lose and loose interchangeably, and that people who live in Northern England are more likely to use the character string than people who live in Hawaii.) Also, my crude method of discounting information by ρ due to pairwise correlations of ρ might not discount enough: I used an estimate based on an Ising model, which is the maximum-entropy (highest information) distribution given the correlation constraints. I haven’t been able to figure out how much lower the information could be in the worst-case.  ↩ People debate if this is true for “intelligence”, but it’s definitely true in terms of bit-rate.  ↩ Also, arguably, stylometry is about language. This means that large language models probably have much of what they need baked in. That might explain why they’re pretty good at it just “by accident”. But to do this optimally I think they’d need self-reflection (e.g. access to probabilities of text given different contexts) that current LLMs aren’t typically capable of, and wouldn’t know how to manipulate correctly without task-specific training.  ↩ You could conjecture that near-optimal stylometry abilities are some kind of “emergent property”. But the general lesson so far is that LLMs mostly don’t have emergent properties but are just good at what they’re trained at.  ↩ (Meta-joke about you—person who works at an AI company—thinking, “maybe we should do that”, coming to this footnote, and seeing this meta-joke.)  ↩ Instead of “homogenizing” writing by imposing a generic style, perhaps it would be better to “camouflage” it by enforcing a very strong but random style.  ↩ Be a little careful here: Typically, the KL-divergence is understood to be measured in nats. But in this article, I’ve measured mutual information in bits. That’s fine, but you need to convert. For example, 106.2 bits = 73.60 nats.  ↩

0 views
ptrchm Yesterday

Postgres Backups to S3 with WAL-G and Kamal

The Kamal setup guides I found online focus on S3 backups using . You don’t want that for a production database. A better solution is to set up your Postgres database for Point-In-Time Recovery (PITR) using WAL-G or pgBackRest. This means your database is continuously archiving WAL segments to an S3 bucket (roughly every 60 seconds), so you can restore to any point in time. With LLMs, it’s not that hard to set up. This quick guide focuses on WAL-G, because I’ve found it to be a lot easier to set up than pgBackRest.

0 views