Friday 22 March 2024

Unicode Numeral Systems 2

Ray Toal recently enlightened me on the existence of two interesting number systems: Kaktovik numerals and Cistercian numerals.

I haven't updated my list of numeral systems since Unicode 14.0.0 (see original blog post), so I thought I'd revisit the whole "Universe" project and update it to Unicode 15.1.0.

The vigesimal Kaktovik numerals are supported by Unicode 15.0.0 (U+1D2C0 to U+1D2D3), but, at the time of writing, Google Noto font support is still shuffling along the pipe, so they are difficult to display:

[source]

Cistercian numerals are interesting as they are (sort of) base-10000, but they have not been allocated a Unicode range, although the proposal dates back to 2020.

[source]

The Cistercian numeral clock tickled my fancy.


Friday 15 April 2022

Unicode Trivia U+10FB

Codepoint: U+10FB "GEORGIAN PARAGRAPH SEPARATOR"
Block: U+10A0..10FF "Georgian"

The Georgian scripts are encoded in four letter forms in three Unicode blocks:

The four rows are:

  1. Asomtavruli is the oldest form, dating from the fifth century CE
  2. Nuskhuri dates from the ninth century CE
  3. Mkhedruli is the current Georgian script
  4. Mtavruli is the uppercase version of Mkhedruli

In the original "Georgian" block, the codepoints U+10A0..10C5 encode the uppercase of the old ecclesiastical alphabet, Asomtavruli (row 1). The codepoints U+10D0..10F0 encode the the lowercase of the modern secular alphabet, Mkhedruli (row 4). The latter is used for almost all text, including at the beginning of sentences and names.

However, don't be tempted to mash together uppercase Asomtavruli with lowercase Mkhedruli to get a bicameral script. That problem wasn't "solved" until the addition of the later "Georgian Extended" and "Georgian Supplement" blocks. More on that in later posts. For modern Georgians, this isn't really a problem at all; writing uses only one case.

In old texts, the "჻" symbol (U+10FB GEORGIAN PARAGRAPH SEPARATOR) was used at the end of the last line of a paragraph. Its use was presumably similar to that of the pilcrow "¶" but at the end of the paragraph, not at the beginning. Alas, the Georgian script didn't get its own full stop; it must share it with the Armenian one, "։" (U+0589 ARMENIAN FULL STOP)

ISO 10586:1996 encodes 42 characters of the Georgian script in a 7-bit character set, including the paragraph mark at 0x4F.

There is an interesting annex in the standard, part of which I'll include below:

Annex A: Development of the Georgian script

Armenian and Georgian, two of the multitudinous tongues spoken in the Caucasian Region, are vehicles of millennial civilizations. Both languages present peculiar phonetic resemblances in spite of their completely different origins. Georgian, or Grusinian, is a member of the Kartvelian language family. Armenian is a member of the Indo-European language family. Each language has its own alphabet, which resemble one another, since the alphabets developed from the same source.

According to one tradition, these two alphabets were invented circa A.D. 406 by the Armenian monk, missionary and theologian Mesrop Mast’oc’ (ca. A.D. 360 to A.D. 439), who also invented an alphabet for the now extinct language Albani (or Caucasian Albanian). According to another tradition, the Georgian script was invented circa A.D. 300 by the Georgian king, Parnavaz. Some scholars allege that it was invented many centuries earlier. The origin of, and the relations between, the three forms of the script are also still in dispute.

More likely, the Georgian script was derived, as was the Armenian script, from a Semitic alphabet, the Pahlavi script, used in Persia in the 4th century. It was developed under a strong Greek influence (by Mast’oc’ or perhaps one of his disciples) into an alphabet enabling the Georgian people to spell their language, with its wealth of sounds in a simple and phonemic way. Owing to phonetic evolution, a few letters became superfluous. In former times, the Georgian alphabet was also used in writing Ossetic and Abkhaz. The oldest inscription in Georgian dates back to the 5th century. The oldest manuscripts date from the 8th century. The period from A.D. 980 to A.D. 1220 is considered the golden age of Georgian literature.

Wednesday 13 April 2022

Unicode Trivia U+1090

Codepoint: U+1090 "MYANMAR SHAN DIGIT ZERO"
Block: U+1000..109F "Myanmar"

The "Myanmar" Unicode block contains glyphs used in various regional writing systems including the Burmese and Shan scripts. In this post, I'm going to play fast and loose with the script names and just call them "Burmese" and "Shan". Unicode Technical Note 11 describes some of the intricacies involved with the various scripts, weighing in at a healthy 67 pages.

The "Myanmar" block contains two sets of digits: one for Burmese (second row below) and one for Shan (bottom row):

If you have appropriate fonts installed, these are the Burmese digits (U+1040..1049):

၀၁၂၃၄၅၆၇၈၉

and Shan digits  (U+1090-1099):

႐႑႒႓႔႕႖႗႘႙

Burmese digits have the advantage (over Hindu-Arabic and Shan digits) of having ascenders and descenders which help to differentiate them. They are very similar to "Tai Tham Hora" digits (U+1A80..1A89). See here.

The Shan script supposedly evolved from the Burmese, but their digits are markedly different. To my eyes, they appear to resemble the Hindu-Arabic digits, but the "8" and "9" are inexplicably similar.

The Burmese language has words for very large numbers: powers of ten up t107 and then increasing multiplicatively by factors of 107 up to 10140 ("athinche", fittingly this is a synonym for "countless number"). I could find no reason why the names progress in multiples of 107. Most other languages use 103 (e.g. English "thousand", "million", "billion", etc.) or sometimes 102 (e.g. Indian "lakh", "crore", "arab", etc.)

Another curiosity is that the tonal pronunciation of digits changes depending on the denary position of the digit within the number. The tone generally changes from "low" to "creaky" (no, really!) for digits in the 101102 and 103 places.

Monday 11 April 2022

Unicode Trivia U+0F33

Codepoint: U+0F33 "TIBETAN DIGIT HALF ZERO"
Block: U+0F00..0FFF "Tibetan"

The Unicode Character Database has a field named "Numeric_Value" (abbreviated to "nv"). For the vast majority of the 144,697 used codepoints in Unicode 14.0.0 (in fact, precisely 142,890) this field holds the value "NaN" meaning that the codepoint does not represent a numeric value.

Other values for "nv", with the number of codepoints having that value in parentheses, are shown below, in approximate order of frequency.

First, the denary digits. The distribution is not flat because of the irregularity of CJK ideographs representing small numbers and the lack of a "zero" digit in some writing systems:

  • "1" (141)
  • "2" (140)
  • "3" (141)
  • "4" (132)
  • "5" (130)
  • "6" (114)
  • "7" (113)
  • "8" (109)
  • "9" (113)
  • "0" (84)

Next, multiples of ten:

  • "10" (62)
  • "20" (36)
  • "30" (19)
  • "40" (18)
  • "50" (29)
  • "60" (13)
  • "70" (13)
  • "80" (12)
  • "90" (12)

Next, powers of ten. Characters for trillions are using in Japan and Taiwan (U+5146) and in the Pahawh Hmong script (U+16B61):

  • "100" (35)
  • "1000" (22)
  • "10000" (13)
  • "100000" (5)
  • "1000000" (1)
  • "10000000" (1)
  • "100000000" (3)
  • "10000000000" (1)
  • "1000000000000" (2)

Next, sequential values up to twenty:

  • "11" (8)
  • "12" (8)
  • "13" (6)
  • "14" (6)
  • "15" (6)
  • "16" (7)
  • "17" (7)
  • "18" (7)
  • "19" (7)

Next, blocks of circled numbers:

  • "21" (1)
  • "22" (1)
  • "23" (1)
  • "24" (1)
  • "25" (1)
  • "26" (1)
  • "27" (1)
  • "28" (1)
  • "29" (1)

  • "31" (1)
  • "32" (1)
  • "33" (1)
  • "34" (1)
  • "35" (1)
  • "36" (1)
  • "37" (1)
  • "38" (1)
  • "39" (1)

  • "41" (1)
  • "42" (1)
  • "43" (1)
  • "44" (1)
  • "45" (1)
  • "46" (1)
  • "47" (1)
  • "48" (1)
  • "49" (1)

Next, multiples of 100. We can see the importance of 500 in ancient counting systems (e.g. "D" in Roman numerals)

  • "200" (6)
  • "300" (7)
  • "400" (7)
  • "500" (16)
  • "600" (7)
  • "700" (6)
  • "800" (6)
  • "900" (7)

Next, multiples of 1000:

  • "2000" (5)
  • "3000" (4)
  • "4000" (4)
  • "5000" (8)
  • "6000" (4)
  • "7000" (4)
  • "8000" (4)
  • "9000" (4)

Next, multiples of 10,000:

  • "20000" (4)
  • "30000" (4)
  • "40000" (4)
  • "50000" (7)
  • "60000" (4)
  • "70000" (4)
  • "80000" (4)
  • "90000" (4)

Next, multiples of 100,000 (e.g. "lakh"):

  • "200000" (2)
  • "300000" (1)
  • "400000" (1)
  • "500000" (1)
  • "600000" (1)
  • "700000" (1)
  • "800000" (1)
  • "900000" (1)

Next, multiples of 10,000,000 (e.g. "crore"):

  • "20000000" (1)

Next are two large numbers from cuneiform (base 60):

  • "216000" (1)
  • "432000" (1)

Next, we start the rational fractions (e.g. "half"):

  • "1/2" (18)

Next, the quarters:

  • "1/4" (13)
  • "3/4" (8)

Next, the eighths:

  • "1/8" (7)
  • "3/8" (1)
  • "5/8" (1)
  • "7/8" (1)

Next, the sixteenths:

  • "1/16" (6)
  • "3/16" (5)

Next, the thirty-seconds:

  • "1/32" (1)

Next, the sixty-fourths:

  • "1/64" (1)
  • "3/64" (1)

Next, the thirds (strangely, there's an Ancient Greek "⅔" U+10177, but not for "⅓"):

  • "1/3" (5)
  • "2/3" (6)

Next, the fifths:

  • "1/5" (3)
  • "2/5" (1)
  • "3/5" (1)
  • "4/5" (1)

Next, the sixths:

  • "1/6" (3)
  • "5/6" (2)

Next, a seventh:

  • "1/7" (1)

Next, a ninth:

  • "1/9" (1)

Next, the twelfths (Meroitic cursive fractions, not reduced):

  • "1/12" (1)
  • "2/12" (1)
  • "3/12" (1)
  • "4/12" (1)
  • "5/12" (1)
  • "6/12" (1)
  • "7/12" (1)
  • "8/12" (1)
  • "9/12" (1)
  • "10/12" (1)
  • "11/12" (1)

Next, a collection of (mostly Tamil and Malayalam) fractions we've seen already:

  • "1/320" (2)
  • "1/160" (2)
  • "1/80" (1)
  • "1/40" (2)
  • "3/80" (2)
  • "1/20" (2)
  • "1/10" (3)
  • "3/20" (2)

Finally, a collection of what can only be described as "strange halves":

  • "3/2" (1)
  • "5/2" (1)
  • "7/2" (1)
  • "9/2" (1)
  • "11/2" (1)
  • "13/2" (1)
  • "15/2" (1)
  • "17/2" (1)
  • "-1/2" (1)

These last nine all belong to the "Tibetan / Digits minus Half" group of codepoints (U+0F2A to U+0F33), including the wonderfully perplexing U+0F33 "TIBETAN DIGIT HALF ZERO".

[source]

This character supposedly has a numeric value of "-1/2" or "-0.5", and is the only codepoint (so far) with a negative "nv".

As Andrew West points out, there is much confusion (and little evidence) surrounding the numeric values of these codepoints. The glyphs seem to appear on postage stamps, but if the Royal Mail was in the habit of issuing stamps with a denomination of minus ½p, they quickly go out of business. If you went into a Post Office and asked for one million "-½p" stamps, the teller would be obliged to give you a huge tome of stamps and £5,000.

Sunday 20 February 2022

Unicode Trivia U+0EA5

Codepoint: U+0EA5 "LAO LETTER LO LOOT"
Block: U+0E80..0EFF "Lao"

The Lao script (Akson Lao) is a sister script of the Thai script; both derive from the Sukhothai script of the thirteenth century CE. As such, they have many similarities. For instance, both Lao and Thai consonants are given individual names. Here are the 27 Lao consonants with their typical names:

  1. ກ = chicken (ໄກ່)
  2. ຂ = egg (ໄຂ່)
  3. ຄ = water buffalo (ຄວາຍ)
  4. ງ = ox (ງົວ)
  5. ຈ = glass (ຈອກ)
  6. ສ = tiger (ເສືອ)
  7. ຊ = elephant (ຊ້າງ)
  8. ຍ = mosquito (ຍຸງ)
  9. ດ = child (ເດັກ)
  10. ຕ = eye (ຕາ)
  11. ຖ = bag (ຖົງ)
  12. ທ = flag (ທຸງ)
  13. ນ = bird (ນົກ)
  14. ບ = goat (ແບ້)
  15. ປ = fish (ປາ)
  16. ຜ = bee (ເຜິ້ງ)
  17. ຝ = rain (ຝົນ)
  18. ພ = mountain (ພູ)
  19. ຟ = fire (ໄຟ)
  20. ມ = cat (ແມວ)
  21. ຢ = medicine (ຢາ)
  22. ຣ = car (ຣົຖ)
  23. ລ = monkey (ລີງ)
  24. ວ = fan (ວີ)
  25. ຫ = goose (ຫ່ານ)
  26. ອ = bowl (ອື່ງ)
  27. ຮ = house (ເຮືອນ)

Each consonant's name begins with that consonant in a similar fashion to English alphabet mnemonics such a "A is for apple, B is for banana, etc.", known as acrophony:

[source]

Alas, the mapping of these consonants to the appropriate "column" of the Unicode Lao block is complicated by two factors:

  1. The Unicode encoding is based loosely on Thai Industrial Standard 620-2533 and has holes where unused characters are omitted.
  2. The names of four of the consonants were incorrect when they were added to Unicode 1.0.

These complications are discussed in Andrew West's N3137 notes:

The Unicode code charts note that the Lao block is "Based on TIS 620-2529". This statement is misleading as TIS 620-2529 is a Thai standard for representing the Thai script in an 8-bit code, and does not define names or code points for the Lao script. The Unicode Lao block is based on a mapping of Lao characters to the equivalent Thai characters in TIS 620, but is not actually based on this standard.

And:

The Unicode names for Lao consonants are based on the syllabic pronunciation of the character (i.e. consonant plus inherent vowel). All consonants belong to one of three tone classes: high, mid and low. Where two letters are only distinguished phonetically by their tone class, the modifiers SUNG "high" and TAM "low" are used to indicate the tone class of the letter (e.g. U+0E82 "LAO LETTER KHO SUNG" and U+0E84 "LAO LETTER KHO TAM"). However, the Unicode names for two of the consonants have the wrong tone class applied to them:

U+0E9D "LAO LETTER FO TAM" is a high tone class letter, and should have been named "LAO LETTER FO SUNG"

U+0E9F "LAO LETTER FO SUNG" is a low tone class letter, and should have been named "LAO LETTER FO TAM"

Whilst the Unicode names for 25 of the 27 consonants use this naming scheme, the names of two of the consonants use mnemonic names (presumably because they share the same vowel and tone class, and so could not otherwise be differentiated). Mnemonic names are how the consonants are normally identified in the Lao language, although there is no official list of standard mnemonic names for consonants, and different sources may use different mnemonic names for some letters.

The two letters whose Unicode names are based on mnemonic names are:

U+0EA3 "LAO LETTER LO LING"

U+0EA5 "LAO LETTER LO LOOT"

The mnemonic names for these two letters are the wrong way round. U+0EA5 is the normal letter [l] and is universally identified by the mnemonic name lo ling "lo as in ling [monkey]". On the other hand, U+0EA3 is a letter that is used to represent [r] in foreign words; however this letter has been officially deprecated by the Lao government since 1975, and is no longer in common use. The name element LO LOOT applied to U+0EA5 would seem to represent the mnemonic ro rot, "rot" meaning automobile, that should be applied to U+0EA3.

So  U+0EA3 should be named "LAO LETTER RO ROT" (car) and U+0EA5 should be named "LAO LETTER LO LING" (monkey).

It is interesting that the Unicode standard has effectively "nailed down" the names of the consonants even though Andrew West says there is no official standard.

It has always troubled me that English does not have a satisfactory mechanism for naming its letters. These are the names typically used in British English:

  1. a
  2. bee
  3. cee
  4. dee
  5. e
  6. eff
  7. gee
  8. aitch
  9. i
  10. jay
  11. kay
  12. el
  13. em
  14. en
  15. o
  16. pee
  17. cue
  18. ar
  19. ess
  20. tee
  21. u
  22. vee
  23. double-u
  24. ex
  25. wye
  26. zed

If we ignore "double-u" (which we've met before), the obvious elephant in the room is "cue" for "Q". Not only is it not acrophonic (only 15 of the 26 truly are), "Q" doesn't appear anywhere in its name.

Monday 14 February 2022

Unicode Trivia U+0E74

Codepoint: U+0E74 "THAI PHONETIC ORDER VOWEL SIGN SARA MAI MALAI"
Block: U+0E00..0E7F "Thai"

Huh? According to Unicode's own lookup utility, U+0E74 is an unassigned codepoint. But that wasn't always the case. Back in Unicode 1.0.0 (October 1991) it was U+0E74 "THAI PHONETIC ORDER VOWEL SIGN SARA MAI MALAI":

[source]

Alas, codepoints U+0E70 to U+0E74 only lasted until Unicode 1.0.1 (June 1992) when they were deleted. This was the only time a non-zero patch version (i.e. "major.minor.patch" where patch ≠ 0) of Unicode was officially released. The stability policy means that another patch release is highly unlikely and the removal of codepoints impossible:

Encoding Stability (since Unicode 2.0)

Once a character is encoded, it will not be moved or removed. 

This policy ensures that implementers can always depend on each version of the Unicode Standard being a superset of the previous version. The Unicode Standard may deprecate the character (that is, formally discourage its use), but it will not reallocate, remove, or reassign the character.

So why was U+0E74 "THAI PHONETIC ORDER VOWEL SIGN SARA MAI MALAI" and its siblings removed? According to the Notice, it was to bring the Unicode and ISO 10646 standards back in line; U+0E74 was never added to ISO 10646. According to the minutes of a May 1992 meeting of the Unicode Technical Committee:

The UTC has noticed the requirement to remove 5 THAI characters (U+0E70 - U+0E74) and 5 LAO characters (U+0EF0 - U+0EF4). In the interest of the merger between ISO 10646 and Unicode the UTC authorizes its representatives attending the SC2/WG2 meeting in Korea to be flexible on this subject.

The juxtaposition of "authorizes" and "flexible" made me smile.

It appears that Thai Phonetic Order Vowel Signs were redundant and could cause ambiguity:

Nowadays, the Thai syllable ไตร, normatively pronounced /trai/, is only encoded <U+0E44 THAI CHARACTER SARA AI MAIMALAI, U+0E15 THAI CHARACTER TO TAO, U+0E23 THAI CHARACTER RO RUA>, and the character U+0E3A is always visible when used; for most routine purposes it is little different to U+0E38 THAI CHARACTER SARA U.  However, in Unicode 1.0[.0], while <U+0E44, U+0E15, U+0E23> was rendered as at present, the same visible string could also be encoded as <U+0E15, U+0E3A, U+0E23, U+0E74 THAI PHONETIC ORDER VOWEL SIGN SARA MAI MALAI> - no glyph would be rendered for U+0E3A.

I think that's implying that the sequence <... U+0E74> could just as easily be encoded as <U+0E44 ...>. The original glyph charts suggest that too:

[source]

Of course, if someone legitimately used U+0E74 in a document between October 1991 and June 1992, their document would become officially invalid or corrupt after June 1992.

Friday 11 February 2022

Unicode Trivia U+0DA5

Codepoint: U+0DA5 "SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA"
Block: U+0D80..0DFF "Sinhala"

As  Richard Gillam says in "Unicode Demystified" (2003), page 330:

The Unicode Sinhala block runs from U+0D80 to U+0DFF. It does not follow the ISCII order, partly because the ISCII standard doesn't include a code page for Sinhala and partly because Sinhala includes a lot of sounds (and, thus, letters) that aren't present in any of the Indian scripts. The basic setup of the block is the same: anusvara and visarga first, followed by independent vowels, consonants, dependent vowels, and punctuation. Unlike in the ISCII-derived blocks, the al-lakuna (virama) precedes the dependent vowels, rather than following them.

The order of codepoints (or of text made up of codepoints) can be thought of in at least three ways:

  1. The order of codepoints within the character set, e.g. Unicode ("codepoint order")
  2. The order of letters in an 'alphabet', e.g. Sinhala abugida ("alphabet order")
  3. The typical order of words in a language's dictionary ("collation order")

As an example, we'll consider the letters (and only the standalone letters) from the Sinhala block (U+0D80..0DFF).

In codepoint order, these are:

  • 18 independent vowels (U+0D85..0D96)
  • 41 consonants (U+0D9A..0DC6)

The alphabet order (according to sites such as Omniglot) is the same as the codepoint order. This was presumably a factor in the ordering of the codepoints when the block was added to Unicode 3.0 in 1999.

However, in "collation order" these 59 letters (along with their Sinhalese and Romanized phonetic names) are:

  1. U+0D85 = "අ" = AYANNA = vowel a
  2. U+0D86 = "ආ" = AAYANNA = vowel aa
  3. U+0D87 = "ඇ" = AEYANNA = vowel ae
  4. U+0D88 = "ඈ" = AEEYANNA = vowel aae
  5. U+0D89 = "ඉ" = IYANNA = vowel i
  6. U+0D8A = "ඊ" = IIYANNA = vowel ii
  7. U+0D8B = "උ" = UYANNA = vowel u
  8. U+0D8C = "ඌ" = UUYANNA = vowel uu
  9. U+0D8D = "ඍ" = IRUYANNA = vowel vocalic r
  10. U+0D8E = "ඎ" = IRUUYANNA = vowel vocalic rr
  11. U+0D8F = "ඏ" = ILUYANNA = vowel vocalic l
  12. U+0D90 = "ඐ" = ILUUYANNA = vowel vocalic ll
  13. U+0D91 = "එ" = EYANNA = vowel e
  14. U+0D92 = "ඒ" = EEYANNA = vowel ee
  15. U+0D93 = "ඓ" = AIYANNA = vowel ai
  16. U+0D94 = "ඔ" = OYANNA = vowel o
  17. U+0D95 = "ඕ" = OOYANNA = vowel oo
  18. U+0D96 = "ඖ" = AUYANNA = vowel au
  19. U+0D9A = "ක" = ALPAPRAANA KAYANNA = consonant ka
  20. U+0D9B = "ඛ" = MAHAAPRAANA KAYANNA = consonant kha
  21. U+0D9C = "ග" = ALPAPRAANA GAYANNA = consonant ga
  22. U+0D9D = "ඝ" = MAHAAPRAANA GAYANNA = consonant gha
  23. U+0D9E = "ඞ" = KANTAJA NAASIKYAYA = consonant nga
  24. U+0D9F = "ඟ" = SANYAKA GAYANNA = consonant nnga
  25. U+0DA0 = "ච" = ALPAPRAANA CAYANNA = consonant ca
  26. U+0DA1 = "ඡ" = MAHAAPRAANA CAYANNA = consonant cha
  27. U+0DA2 = "ජ" = ALPAPRAANA JAYANNA = consonant ja
  28. U+0DA5 = "ඥ" = TAALUJA SANYOOGA NAAKSIKYAYA = consonant jnya
  29. U+0DA3 = "ඣ" = MAHAAPRAANA JAYANNA = consonant jha
  30. U+0DA4 = "ඤ" = TAALUJA NAASIKYAYA = consonant nya
  31. U+0DA6 = "ඦ" = SANYAKA JAYANNA = consonant nyja
  32. U+0DA7 = "ට" = ALPAPRAANA TTAYANNA = consonant tta
  33. U+0DA8 = "ඨ" = MAHAAPRAANA TTAYANNA = consonant ttha
  34. U+0DA9 = "ඩ" = ALPAPRAANA DDAYANNA = consonant dda
  35. U+0DAA = "ඪ" = MAHAAPRAANA DDAYANNA = consonant ddha
  36. U+0DAB = "ණ" = MUURDHAJA NAYANNA = consonant nna
  37. U+0DAC = "ඬ" = SANYAKA DDAYANNA = consonant nndda
  38. U+0DAD = "ත" = ALPAPRAANA TAYANNA = consonant ta
  39. U+0DAE = "ථ" = MAHAAPRAANA TAYANNA = consonant tha
  40. U+0DAF = "ද" = ALPAPRAANA DAYANNA = consonant da
  41. U+0DB0 = "ධ" = MAHAAPRAANA DAYANNA = consonant dha
  42. U+0DB1 = "න" = DANTAJA NAYANNA = consonant na
  43. U+0DB3 = "ඳ" = SANYAKA DAYANNA = consonant nda
  44. U+0DB4 = "ප" = ALPAPRAANA PAYANNA = consonant pa
  45. U+0DB5 = "ඵ" = MAHAAPRAANA PAYANNA = consonant pha
  46. U+0DB6 = "බ" = ALPAPRAANA BAYANNA = consonant ba
  47. U+0DB7 = "භ" = MAHAAPRAANA BAYANNA = consonant bha
  48. U+0DB8 = "ම" = MAYANNA = consonant ma
  49. U+0DB9 = "ඹ" = AMBA BAYANNA = consonant mba
  50. U+0DBA = "ය" = YAYANNA = consonant ya
  51. U+0DBB = "ර" = RAYANNA = consonant ra
  52. U+0DBD = "ල" = DANTAJA LAYANNA = consonant la
  53. U+0DC0 = "ව" = VAYANNA = consonant va
  54. U+0DC1 = "ශ" = TAALUJA SAYANNA = consonant sha
  55. U+0DC2 = "ෂ" = MUURDHAJA SAYANNA = consonant ssa
  56. U+0DC3 = "ස" = DANTAJA SAYANNA = consonant sa
  57. U+0DC4 = "හ" = HAYANNA = consonant ha
  58. U+0DC5 = "ළ" = MUURDHAJA LAYANNA = consonant lla
  59. U+0DC6 = "ෆ" = FAYANNA = consonant fa
Spot the anomaly? Well, U+0DA5 "SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA" is out of order.
U+0DA5 from r12a

As an English speaker, the codepoint order, alphabet order and collation order of the letters "A" to "Z" are identical; so having subtle anomalies like this feels jarring. So jarring, in fact, that I checked it against three different sources (Unicode CLDR, MySQL and dictionary.gov.lk) to make sure I hadn't made a transcription error.

It's a bit like having the English alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ" but listing words in an English dictionary in a different order, such as "ABCDEFGHIJKLPMNOQRSTUVWXYZ".

You only really need to nail down the order of letters of an writing system when you start creating reference dictionaries. However, as the Sinhala Dictionary Compilation Institute says, this didn't happen until British colonial rule of what became Sri Lanka. It's impossible to imagine that the British compilers didn't impose some of their preconceptions on the process and therefore muddied the ordering waters.

As Richard Gillam pointed out, Sinhala has a large number of letters and U+0DA5 "SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA" is one of those that doesn't fit into the canonical Brahmic consonant ordering utilised by ISCII.

survey by Weerasinghe, Herath and Gamage (2006) supplies many definitions of Sinhalese "dictionary order" in current use. Indeed, even if Unicode CLDR collation is adopted as a single de facto standard, the collation tailoring metadata is considered "live", and therefore liable to change anyway.