circuitpython/supervisor/shared
Jeff Epler 07740d19f3 add bigram compression to makeqstrdata
Compress common unicode bigrams by making code points in the range
0x80 - 0xbf (inclusive) represent them.  Then, they can be greedily
encoded and the substituted code points handled by the existing Huffman
compression.  Normally code points in the range 0x80-0xbf are not used
in Unicode, so we stake our own claim.  Using the more arguably correct
"Private Use Area" (PUA) would mean that for scripts that only use
code points under 256 we would use more memory for the "values" table.

bigram means "two letters", and is also sometimes called a "digram".
It's nothing to do with "big RAM".  For our purposes, a bigram represents
two successive unicode code points, so for instance in our build on
trinket m0 for english the most frequent are:
['t ', 'e ', 'in', 'd ', ...].

The bigrams are selected based on frequency in the corpus, but the
selection is not necessarily optimal, for these reasons I can think of:
 * Suppose the corpus was just "tea" repeated 100 times.  The
   top bigrams would be "te", and "ea".  However,
   overlap, "te" could never be used.  Thus, some bigrams might actually
   waste space
    * I _assume_ this has to be why e.g., bigram 0x86 "s " is more
      frequent than bigram 0x85 " a" in English for Trinket M0, because
      sequences like "can't add" would get the "t " digram and then
      be unable to use the " a" digram.

 * And generally, if a bigram is frequent then so are its constituents.
   Say that "i" and "n" both encode to just 5 or 6 bits, then the huffman
   code for "in" had better compress to 10 or fewer bits or it's a net
   loss!
    * I checked though!  "i" is 5 bits, "n" is 6 bits (lucky guess)
      but the bigram 0x83 also just 6 bits, so this one is a win of
      5 bits for every "it" minus overhead.  Yay, this round goes to team
      compression.
    * On the other hand, the least frequent bigram 0x9d " n" is 10 bits
      long and its constituent code points are 4+6 bits so there's no
      savings, but there is the cost of the table entry.
    * and somehow 0x9f 'an' is never used at all!

With or without accounting for overlaps, there is some optimum number
of bigrams.  Adding one more bigram uses at least 2 bytes (for the
entry in the bigram table; 4 bytes if code points >255 are in the
source text) and also needs a slot in the Huffman dictionary, so
adding bigrams beyond the optimim number makes compression worse again.

If it's an improvement, the fact that it's not guaranteed optimal
doesn't seem to matter too much.  It just leaves a little more fruit
for the next sweep to pick up.  Perhaps try adding the most frequent
bigram not yet present, until it doesn't improve compression overall.

Right now, de_DE is again the "fullest" build on trinket_m0.  (It's
reclaimed that spot from the ja translation somehow)  This change saves
104 bytes there, increasing free space about 6.8%.  In the larger
(but not critically full) pyportal build it saves 324 bytes.

The specific number of bigrams used (32) was chosen as it is the max
number that fit within the 0x80..0xbf range.  Larger tables would
require the use of 16 bit code points in the de_DE build, losing savings
overall.

(Side note: The most frequent letters in English have been said
to be: ETA OIN SHRDLU; but we have UAC EIL MOPRST in our corpus)
2020-09-01 17:12:22 -05:00
..
external_flash Add license to some obvious files. 2020-07-06 19:16:25 +01:00
usb Merge pull request #3225 from hathach/improve-highspeed-usb 2020-07-30 07:15:20 -05:00
autoreload.c Updates based on feedback from jepler 2020-04-06 16:03:31 -07:00
autoreload.h Refine _bleio 2019-10-21 18:57:03 -07:00
background_callback.c background callbacks: Clear any callbacks that were queued 2020-07-20 08:44:39 -05:00
bluetooth.c wip: advertising; not tested 2020-07-12 19:45:23 -04:00
bluetooth.h wip: compiles 2020-08-02 11:36:38 -04:00
board.c pygamer and pybadge boards were not resetting neopixels 2020-01-24 09:32:28 -05:00
board.h reset NeoPixels on CPB on soft reload 2020-01-23 20:16:31 -05:00
display.c Turn off terminalio for ja and ko 2020-08-17 17:17:59 -07:00
display.h Turn off terminalio for ja and ko 2020-08-17 17:17:59 -07:00
filesystem.c Allow drive name to be set per target, with fallback to pre-existing behaviour 2020-02-12 11:09:48 +00:00
flash.c flash: Correctly signal error on invalid flash read 2020-06-22 10:24:21 -05:00
internal_flash.h Hopefully fix flash flush and hopefully audio as well. 2020-03-13 11:12:31 -07:00
memory.c Initial ESP32S2 port. 2020-05-15 15:36:16 -07:00
micropython.c supervisor: use mp_handle_pending to check for exceptions 2020-08-23 09:12:01 -05:00
rgb_led_colors.h Reduce DotStar status brightness; macros for status colors 2019-11-01 13:37:36 -04:00
rgb_led_status.c Fix RGB LED use 2020-08-24 18:29:50 -07:00
rgb_led_status.h Disable bitbangio on Itsy M0 2019-08-27 15:21:47 -07:00
safe_mode.c safe_mode: Exclude NORDIC_SOFT_DEVICE_ASSERT str if possible 2020-08-04 14:45:45 -05:00
safe_mode.h supervisor: add a new WATCHDOG_RESET safe mode reason 2020-05-27 11:28:49 +08:00
serial.c Turn off terminalio for ja and ko 2020-08-17 17:17:59 -07:00
stack.c Initial ESP32S2 port. 2020-05-15 15:36:16 -07:00
stack.h Initial ESP32S2 port. 2020-05-15 15:36:16 -07:00
status_leds.c Add feature conditionals and clean up 2019-07-22 12:58:28 -04:00
status_leds.h Move atmel-samd to tinyusb and support nRF flash. 2018-11-08 17:25:30 -08:00
tick.c merge from upstream 2020-08-30 14:39:03 -04:00
tick.h supervisor: factor supervisor_background_tasks from sundry ports 2020-07-15 11:49:44 -05:00
translate.c add bigram compression to makeqstrdata 2020-09-01 17:12:22 -05:00
translate.h translations: document the compressed format 2020-05-28 11:30:46 -05:00