HNHacker News
TopNewBestAskShowJobs

garethrees

532 karma · joined November 22, 2014

submissionscomments
garethrees··on The world of Dante's Divine Comedy
Looking at Inferno book 4 (the virtuous pagans), Jacopo gives us notes for the Pleiad Electra at 4.121; for Hector at 4.122; Julius Caesar at 4.123; Camilla and Penthesilea at 4.124; Latinus at 4.125; Brutus, Julia, Marcia, and Cornelia at 4.127; Saladin at 4.129; Democritus at 4.136.

But he does not give notes for Abel, Noah, Moses at 4.55; Abraham, David, Israel and Rachel at 4.58; Homer, Horace, Ovid and Lucian at 4.88; Aristotle at 4.130; Socrates and Plato at 4.133; Diogenes, Thales, Anaxagoras, Zeno, Heraclitus, and Empedocles at 4.136; Dioscorides, Orpheus, Cicero, Linus, and Seneca at 4.139; Euclid, Ptolemy, Hippocrates, Galen, Avicenna, and Averroës at 4.142.

So Jacopo, at any rate, thought that readers might need help with mythological and historical references, but not with biblical and philosophical; or maybe he thought it was clear enough from the text that Diogenes, Thales, Anaxagoras, etc. were pagan philosophers. But Guido da Pisa's 1328 commentary has detailed notes on all of these. So there must have been readers who wanted more information on these figures.

garethrees··on The world of Dante's Divine Comedy
I am not sure that "Dante is clearly writing in the expectation that his audience will know these references" as claimed in the article. He put a lot of learning into the work, and maybe he had in mind an ideal reader who could follow the most obscure of references, and appreciate all the allegorical meanings, but it's noticeable that the narrator of the poem is always asking naïve questions and getting rebuked for his ignorance by Virgil and Beatrice. Readers who don't understand everything in the poem can thus feel that they are in a similar position to the narrator.

And as soon as the poem was published, people started writing explanations for the difficult bits. Dante's son Jacopo wrote a commentary in 1322, Graziolo Bambaglioli wrote another in 1324, and by the end of the 14th century there were at least fifteen. This shows that the poem quickly found an audience that was not familiar with all the references.

garethrees··on Defamed by ChatGPT
Language models are based on probabilities of tokens appearing in a context. For illustration purposes, imagine a very simple model with just one token of context that has been trained on a corpus of three sentences, all of which are true, for example:

    clouds are white
    crows are black
    swans are white
After the model outputs "crows are", the single token of context is "are", and the probabilities are 2/3 for "white" and 1/3 for "black". So the model usually emits "crows are white", which is false, despite being trained on a corpus of true statements. Statistically "white" was more likely to follow "are" in the training data, so the same is the case of the model's output.

Of course LLMs have a much larger and more complex context than the single token in my example. But if the training data contains many news stories about professors being accused of sexual misconduct (which is newsworthy), and few news stories about professors behaving with propriety (which is not), then when querying the model for a story about a professor then it is likely to reproduce the statistical properties of its training data.

garethrees··on The benefits of everything being a buffer in Emacs
Another way to sum a column of numbers uses calc:

  M-x calc-grab-rectangle RET V R +
garethrees··on Gimp 2.10.32 on Apple Silicon (2022)
A couple of issues that came up for me when porting from x86 to ARM recently:

1. The x86 architecture gives programmers a lot of memory ordering guarantees, so that communication of values between threads does not usually need memory fences. ARM64 does not give so many guarantees, meaning that multi-threaded code may need additional memory fences to avoid data races. But data races due to out-of-order memory updates are hard to diagnose.

2. Page size in macOS is 4 kB on x86, but 16 kB on ARM, so if someone has hard-coded the page size rather than calling sysconf(_SC_PAGESIZE) this may need to be discovered and fixed.

garethrees··on A seamstress who solved the ancient mystery of the Argonaut
Jeannette Power's "Observations physiques sur le poulpe de l'Argonauta argo" (1856) is available at the Internet Archive [1].

[1] https://archive.org/details/b2228476x

garethrees··on The Mystery of Numerical Notation on the Dial Plate – 4 Is Expressed as IIII
This bit of speculation goes back at least to David Eugene Smith (1925), "History of Mathematics", volume II, page 59:

"There is a possibility that the Romans avoided IV, the initials of IVPITER, just as the Hebrews avoided יה in writing 15, as the Babylonians avoided their natural form for 19, and as similar instances of reverence for or fear of deity occur in other languages."

https://archive.org/details/in.ernet.dli.2015.201939/page/n7...

garethrees··on Why did we wait so long for the bicycle?
> Typically pretty wet weather for the (spring) race

Paris–Roubaix is certainly memorable when it's wet and muddy, but the last time it happened was in 2002! Early spring is the driest part of the year in north-eastern France, and so the usual conditions for the race are dry and dusty. See the Inner Ring: https://inrng.com/2016/04/rain-for-roubaix/

garethrees··on GCC should warn about 2^16 and 2^32 and 2^64
A warning heuristic needs to have a low false positive rate; a low false negative rate is nice but is not necessary. The purpose of a warning is to detect some common errors without inconveniencing too many correct programs. If some other errors go undetected then that is a shame but at least it is no worse than the current situation.
garethrees··on Cycling commissioners say painted bike lanes don’t make cyclists feel safer
Here's the letter from Chris Boardman and the other commissioners, which doesn't seem to be linked from the Guardian story: https://www.greatermanchester-ca.gov.uk/media/2145/19-1309-s...
garethrees··on GCC should warn about 2^16 and 2^32 and 2^64
This seems like a good idea to me, since there's evidence that programmers are making this mistake, and the proposal is to add a warning only for the expressions that are most likely to be mistakes, that is 2^{decimal integer literal} and maybe also 10^{decimal integer literal}. There are many constructs that are well-defined in C, but where it is helpful to have warnings: use of = in condition expressions, implicit fallthrough in switch statements, misleading indentation, unsafe multiple statement macros, and so on. Programming in C is hard enough that every bit of compiler support is valuable.
garethrees··on Downs–Thomson paradox
Discussed a couple of days ago in the context of average Uber speeds in London and other congested cities [1].

[1] https://news.ycombinator.com/item?id=20113084

garethrees··on Uber data reveals motoring slower than walking in many cities
This is a well-known principle of urban transport. If driving is faster than the alternative transport mode (whether that's public transport, if any, or walking), then at the margins people will switch to driving, but that means more traffic on the road, more congestion, and slower driving speeds. Conversely, if driving is slower than the alternative, then at the margins people will switch away from driving, reducing traffic and increasing driving speeds. So in places where road space is the bottleneck, we expect driving speed to be similar to the speed of the alternative mode. In central London, for example, travel speed has been roughly the same whether you drive or take the Underground, for more than a century.

Update since some commenters seem to be having trouble: this process depends on the travellers "at the margin", that is, the people who are most willing to switch modes to reduce their journey time. Thinking in terms of the average or typical traveller is misleading.

garethrees··on Rare Persian manuscripts dating back to 13th century now online
The difficulty of Chaucer for modern English speakers is exaggerated because of the unfamiliar spelling. The reason that modern editions don't modernise the spelling is that if you do this it becomes hard to figure out the rhythm. For example, in the Ellesmere manuscript [1], line 9 is "And smale foweles maken melodye", but if you modernise this to "And small fowls make melody" then you only have seven syllables and it is hard to figure out how this was ever scanned as iambic pentameter. Modern editions end up compromising between spelling and scansion, making the language more difficult-looking than it really is.

[1] https://www.bl.uk/collection-items/ellesmere-manuscript

garethrees··on Writing a Simple Password Generator in Racket
This one-line shell script is a bit simpler:

    base64 /dev/urandom | head -c 16
(Vary the number of characters according to the desired entropy: you get 6 bits of entropy for each character of output, so 16*6 = 96 bits in the example. Use /dev/random or /dev/arandom if you prefer those random sources.)

For passphrases, use GNU shuf (from the coreutils package):

    shuf -n 4 --random-source=/dev/urandom /usr/share/dict/words
garethrees··on The hard part in becoming a command line wizard
It's slightly more efficient to squeeze non-alphabetic characters first and then convert to lowercase, rather than vice versa, because in the former case most of the non-alphabetic characters only get processed once, compared to twice in the latter case.
garethrees··on The hard part in becoming a command line wizard
McIlroy's claim was not that his script is the shortest possible way to implement the task, but rather that the Unix philosophy of combining general-purpose tools operating on text streams is a better engineering approach than Knuth's special-purpose program, because the general-purpose tools can be reused in many ways.

McIlroy: "A first engineering question to ask is: how often is one likely to have to do this exact task’? Not at all often, I contend. It is plausible, though, that similar, but not identical, problems might arise. A wise engineering solution would produce—or better, exploit—reusable parts." [1]

[1] https://www.cs.tufts.edu/~nr/cs257/archive/don-knuth/pearls-...

garethrees··on The de Havilland Comet
The film was based on the novel "No Highway" (1948) by Nevil Shute, who had worked as an aeronautical engineer at De Havilland.
garethrees··on Elsevier journal editors resign, start rival open-access journal
Do you mean Aaron Swartz?
garethrees··on 9999999999999999.0 – 9999999999999998.0
The linked post is a bit poorly expressed, but I think there is a good point there: fixed-size binary floating-point numbers are a compromise, and they are a poor compromise for some applications, and difficult to use reliably without knowing about numerical analysis. (For example, suppose you have an array of floating-point numbers and you want to add them up, getting the closest representable approximation to the true sum. This is a very simple problem and ought to have a very simple solution, but with floating-point numbers it does not [1].)

Perhaps it is time for the developers of new programming languages to consider using a different approach to representing approximations to real numbers, for example something like the General Decimal Arithmetic Specification [2], and to relegate fixed-size binary floating-point numbers to a library for use by experts.

There is an analogy with integers: historically, languages like C provided fixed-size binary integers with wrap-around or undefined behaviour on overflow, but with experience we recognise that these are a poor compromise, responsible for many bugs, and suitable only for careful use by experts. Modern languages with arbitrary-precision integers are much easier to write reliable programs in.

[1] https://en.wikipedia.org/wiki/Kahan_summation_algorithm [2] http://speleotrove.com/decimal/decarith.html

garethrees··on Search is on for Google workers leaking secrets
The description must be sufficiently similar to something that did happen, though, for you to be confident that you recognise the incident.
garethrees··on Undefined Behavior Is Really Undefined
In C you avoid signed integer overflow either by knowing that the result will be in range before applying an operation, or, as a last resort, by testing that the operation is defined before carrying it out. For example, if a and b are ints, then a + b is defined if (a >= 0 && b <= INT_MAX - a) || (a < 0 && b >= INT_MIN - a).

Additionally, some compilers can insert code to detect signed integer overflow at runtime. Clang has the -fsanitize=undefined flag [1].

[1] https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html

garethrees··on Before envelopes, people protected messages with letterlocking
The purpose of the letter lock is to detect tampering: that is, to make it difficult for an eavesdropper to open and read the letter without leaving evidence of having done so.

The standard letter lock was a wax seal: that is a blob of sealing wax with an impression of a stamp or signet ring. A signet ring had an intricate design that was difficult to forge.

A standard wax seal could be defeated by sliding a thin heated knife between the seal and the paper. This melted a little of the wax at the base of the seal, enough to separate it from the paper. Then the letter could be read and the wax seal reattached using the same heated knife.

The purpose of the complex letter locks described in the article was to make the hot knife technique more difficult, by embedding the end of a cut-out strip of paper into the seal so that when the eavesdropper slid their hot knife underneath the seal it would cut the strip.

garethrees··on Memory Allocators 101 – Write a simple memory allocator (2016)
There doesn't seem to be any pointer dereference on the line that paavoova quoted, so I don't see how your comment applies.
garethrees··on Memory Allocators 101 – Write a simple memory allocator (2016)
The cast is defined by ISO/IEC 9899:1990 §6.3.2.3.1, since block is a pointer to void, and struct header_t is an object type:

"A pointer to void may be converted to or from a pointer to any incomplete or object type."

The subtraction is defined by §6.5.6.8, provided that block points to an element of a large enough array object:

"When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression."

(There's similar text in other versions of the C standard.)

garethrees··on The Python Unicode Mess
There is a particular use case which leads to frustration with Python 3, if you don't know the latin1 trick.

The use case is when you have to deal with files that are encoded in some unknown ASCII-compatible encoding. That is, you know that bytes with values 0–127 are compatible with ASCII, but you know nothing whatsoever about bytes with values 128–255.

The use case arises when you have files produced by legacy software where you don't know what the encoding is, but you want to process embedded ASCII-compatible parts of the file as if they were text, but pass the other parts (which you don't understand) through unchanged (for example, the files are documents in some markup language, and you want to make automatic edits to the markup but leave the rest of the text unchanged). Processing as text requires you to decode it, but you can't decode as 'ascii' because there are high-bit-set characters too.

The trick is to decode as latin1 on input, process the ASCII-compatible text, and encode as latin1 on output. The latin1 character set has a code point for every byte value, and bytes with the high bit set will pass through unchanged. So even if the file was actually utf-8 (say), it still works to decode and encode it as latin1, and multi-byte characters will survive this process.

The latin1 trick deserves to be better known, perhaps even a mention in the porting guide.

garethrees··on Bicycle Technology (1973) [pdf]
> Mind you he still that the bottom spokes of a wheel are in compression

I think you might want to read pages 7–8 again: "Wires must be tensioned to prevent their buckling under load. With tension, wires can support compression loads up to the point where they become slack. The same loads that increase compression in wooden spokes, reduce tension in wires. As in algebra, where negative and positive numbers are combined to give algebraic sums, in spokes tension and compression are the negative and positive forces whose sums depends on built-in spoke tension and the carried load."

So the bottom spokes can support a compressive load because this is smaller than their unloaded tension.

garethrees··on Computational Duplo train track layouts
Ian Stewart's article in Scientific American was based on "Train Sets" by Adam Chalcraft and Michael Greene (Eureka 53, pp. 5–12), which also provides the basis of the Duplo constructions. (But note that Duplo has linked points as well as sprung and lazy points, which allows for more compact constructions.)

http://www.monochrom.at/turingtrainterminal/Chalcraft.pdf

garethrees··on Portugal electricity generation temporarily reaches 100% renewable
This is a great achievement, but the headline is misleading because it's only Portugal's ELECTRICITY GENERATION that (temporarily) reached 100% renewable, and electricity constitutes only about 25% of Portugal's energy consumption (source: Eurostat). A further 15% or so of Portgual's energy consumption is renewable in other forms (wood burning, biodiesel), but that leaves a large majority of fossil fuels (about 50% petroleum for transport and 10% natural gas for heating).
garethrees··on Beep security update
This is a good question and doesn't deserve to be downvoted.

I think the reason must be that the problem lies in the intersection of three areas of development (the C programming language, the C standard library, and the POSIX operating system definition) and so requires coordination to solve.

Think about how you would implement warnings for failures of async-signal-safety. One approach would go like this:

1. In compiler front-ends, introduce a new attribute that can be attached to function declarations to indicate that they are async-signal-safe, for example __attribute__((async_signal_safe)), and a new attribute that can be attached to function parameters and struct members to indicate that the passed value must be async-signal-safe, for example __attribute__((require_async_signal_safe)).

2. In C library headers, apply the async_signal_safe attribute to all the async-signal-safe function declarations, and apply the require_async_signal_safe attribute to the parameter to the signal function and to the sa_handler member of struct sigaction.

3. In compilers, propagate the async_signal_safe attribute, so that any function that only calls async_signal_safe functions is also marked with the attribute.

4. In compilers, check that when a function is passed to a parameter or assigned to a member with the require_async_signal_safe attribute, the function is marked with the async_signal_safe attribute, and issue a warning if not.

This doesn't solve the whole problem (sometimes the compiler will not be able to know which function is going to be passed as the parameter to signal, because this is determined at runtime), and it might have false positives in obscure situations (you might in theory use a struct sigaction for some other purpose and never pass it to sigaction) but it would catch many cases, including the one in beep.

But notice the amount of coordination required. It would require input from several people with different areas of expertise.

Page 1 of 3Next →