[header]

Dec. 31st, 2030 11:00 pm
netch80: (finch)
Это субжурнал для [livejournal.com profile] netch по тематике IT. Все вопросы - к оригиналу.
Заголовок журнала - из юморески журнала "Информатика и образование" района 1988 года. У кого есть экземпляр - киньте plz хотя бы скан пары страничек с ним :)
Комментарии к постингу скрываются, если хотите что-то написать лично.
netch80: (Default)
А объясните plz как пятилетнему. Я понимаю, как при норме 230 вольт можно получить в розетке 180 или 250: есть разные виды корректировки под нагрузку или перекос фаз. Но откуда может быть там же 70 или 600, как наблюдалось с развалом сетей? Ну кроме вариантов, что напутали с коммутацией?
netch80: (Default)
Windows 11 Explorerʼs "widgets" (which show weather, stock exchange news, and other boring litter) create a bunch of empty files named "xml_file (number).xml", where number may be a very big integer (Iʼve seen 1228 after 5 days of an account life) in ~/AppData/Local/Temp/.

Here, anything is really superb. Not cleaned-up files. Empty files for nothing. Finally, it is able to iterate any count of possible entries just to find a free one.

Iʼm extremely delighted all this is still working. Anyway, great thanks to it for the idea to disable "widgets".
netch80: (finch)
Как-то очень плавно и незаметно сократился на порядки интерес к такому руководству, как Smart Questions. Говорю это как хостер некогда популярной копии-перевода. Статистику не вёл, увы, цифр и графиков не будет.

Случилось это задолго до нынешнего бума ИИ (имитаторов интеллекта) и перехода большинства подобных вопросов к неразумным, но многословным и дружелюбным отвечалкам, которые осмысленно отвечают на любой вопрос. Но ИИ будет только усугублять разрыв: не надо учиться быть корректным, точным и не грубым. Дальше тут могла быть длинная бурная филиппика, повторяющая тезисы киберпанка и НФ про деградацию человеческого общения и замену людей роботами, пропущу по очевидности.
netch80: (Default)
At least third embedded-related project that I found being used constructions like:

uint8_t i;
for (i = 0; i < 100; ++i) {
  do something
}


Even there is known that the value is limited to be fully present in such a narrow type, it is harmful to use it this way. C/C++ compilers shall apply width extension to a value on each iteration, due to the usual «integral promotion», this is 1) an excessive action, 2) may mask the problem around the maximal value, in case like:

uint8_t slot;
for (i = 0; i < nslots; ++i) {
  do something
}


if nslots == 256, the index is formally valid, but the loop will be forever, because after 255 the next value of `i` will be 0, and the exit condition never succeeds.

In machine code, this entails either iteration on registers like AL (in x86), which causes false sharing with rest of EAX (RAX), or an explicit masking (width extension):

void foo(unsigned n) {
  uint8_t i;
  for (i = 0; i < n; ++i) {
    moo(i);
  }
}


GCC, x86:

foo:
        testl   %edi, %edi
        je      .L9
        pushq   %rbp
        movl    %edi, %ebp
        xorl    %edi, %edi
        pushq   %rbx
        xorl    %ebx, %ebx
        subq    $8, %rsp
.L3:
        call    moo@PLT
        addl    $1, %ebx
        movzbl  %bl, %edi ; <-- Oops!
        cmpl    %ebp, %edi
        jb      .L3
        addq    $8, %rsp
        popq    %rbx
        popq    %rbp
        ret


GCC, AArch64:

foo:
        cbz     w0, .L9
        stp     x19, x20, [sp, -32]!
        mov     w20, w0
        mov     w19, 0
        str     x30, [sp, 16]
.L3:
        mov     w0, w19
        bl      moo
        add     w1, w19, 1
        and     w19, w1, 255
        cmp     w20, w1, uxtb ; <-- Oops!
        bhi     .L3
        ldr     x30, [sp, 16]
        ldp     x19, x20, [sp], 32
        ret
.L9:
        ret


And even if there is no such an effect, there is no need to use such types for local variables, they have sense exclusively in external interfaces like structure members (and in fitting verification for such members).
netch80: (Default)
To make `mc` really open LibreOffice file (odt) for editing in Kubuntu 22.04, I had to purge the `wslu` package which seems to be installed by the default installer — Iʼve certainly not installed it intentionally.
mcʼs ext.sh calls `xdg-open` and stops if it reports success. `xdg-open` reported success although the called program `kde-open5` failed with WSL interaction. Somewhere in this chain, the failure fact was dropped.

Too tangled, as for my normal leisure.

AnyHack-8

Jun. 5th, 2025 06:27 pm
netch80: (finch)
CESU-8 disallows what is allowed in WTF-8 or MUTF-8.

WTF-8 disallows what is allowed in CESU-8 or MUTF-8.

MUTF-8 disallows what is allowed in WTF-8 or CESU-8.

I find this discriminational. All these hacks are mutually compatible. Why canʼt anybody combine them?
netch80: (Default)
Seems apparent, but only after occasionally found this.


>>> "{}".format(math.pi)
'3.141592653589793'
>>> "{:{}}".format(math.pi, 'f')
'3.141593'
>>> "{:{}}".format(math.pi, '.14f')
'3.14159265358979'

>>> f"{math.pi}"
'3.141592653589793'
>>> pr=10
>>> f"{math.pi:.{pr}e}"
'3.1415926536e+00'


And even:


>>> "{:{}}".format(math.pi, '.16e')
'3.1415926535897931e+00'
>>> f"{math.pi:{'.12e'}}"
'3.141592653590e+00'


But this way isnʼt allowed:


>>> f"{math.pi:{\".12e\"}}"
  File "", line 1
    f"{math.pi:{\".12e\"}}"
                           ^
SyntaxError: f-string expression part cannot include a backslash


but we can override it with a trick:


>>> f"{math.pi:{'.12e'}}"
'3.141592653590e+00'
>>> f"""{math.pi:{".12e"}}"""
'3.141592653590e+00'


Not an often case but still useful.

%a

Mar. 13th, 2025 07:00 am
netch80: (Default)
Из серии "мелких удивлений", почему так всё странно:
Когда появилась двоичная плавающая точка, естественно было бы ожидать, что сразу появится и вариант текстового ввода-вывода в двоичном виде (возможно, свёрнутого до восьмеричного или шестнадцатиричного), который даёт:
1) точность передачи значения;
2) избавление от сложного и дорогого кода преобразования путём умножения и деления (который ещё долго был неточным, а для точного требуется многословная арифметика - для double это 1000+ бит в предельном случае, а ещё база констант в помощь самому преобразованию и тонкая шлифовка частных случаев).

Пример: "0x1.921fb54442d18p+1" (число π в double).

Тем не менее, в Fortran этого нет до сих пор, насколько я знаю - а там я ожидал бы в первую очередь. В C появилось в C99 ("%a" в printf, scanf). Аналогичные форматные методы ещё в десятке актуальных языков (Go, Lua, Matlab, OCaml, Perl, PHP, R, Ruby, Rust, Swift, Zig, спасибо ИИ за поиск). В C++ - режим iostream, с C++11 (std::hexfloat). В Python, Ada, Java, Julia, Haskell - нет форматного знака, есть отдельные методы (например, hex(), from_hex()). В некоторых других - требуются отдельные библиотеки, особенно странно про Javascript, где и целых-то нет, есть double на всё.

Инерция эта выглядит более психологическим, чем технологическим фактором.
netch80: (finch)
Я понимаю, что занимаюсь левыми вещами, но иногда надо отвлечься...
У клавиатур есть такое понятие, как ghosting. Обычно его описывают так: если в матрице на пересечении двух строк и двух столбцов нажаты три клавиши, то надо сразу отвергнуть якобы нажатие четвёртой, потому что его реально нет. (Вариант с диодом на каждую клавишу не считаем, банально.) Описание недостаточное, проблема начинается уже при двух клавишах.

Обозначим клавиши как строка/столбец, перебор идёт по строкам со считыванием значений столбцов. Пусть у нас уже зажаты две клавиши: 1/1 и 2/2. Любое из нажатий 1/2 и 2/1 (если физически определены обе) уже должно быть отсечено, потому что мы не можем распознать, какая из них реально нажата.

Возьмём QMK как, вероятно, самый отработанный проект. Смотрим quantum/keyboard.c, matrix_task() и has_ghost_in_row(). Выполняется рескан текущего состояния клавиш. Если есть изменения, перебираем строки. Текущая строка сравнивается со всеми прочими, и если в bitand текущей строки с какой-то другой есть >=2 установленных бита из реально существующих клавиш (отсутствующие согласно карте раскладки - удаляются до этого bitand), то объявляется "призрак" и строка пропускается из рассмотрения на данном этапе.

Теперь добавляем в реальную картину дребезг. Нажимаем 1/2. Пусть пока мы добежали в скане до 1/2, на ней читается отсутствие контакта. Но когда добежали до 2/1, контакт есть и через путь 1/1-1/2-2/2 читается реальный призрак на 2/1. Фиксируем нажатие 2/1, а когда на следующем скане 1/2 окончательно зафиксируется, игнорируем её. В результате срабатывает совсем не то, что должно было бы.

Что я не учёл?
netch80: (finch)
В Ubuntu (22, 24) сделали пакость: dpkg-reconfigure unattended-upgrades ставит в /etc/apt/apt.conf.d/20auto-upgrades:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";


оба параметра в 1 или 0, в результате оно или само всё молча обновляет, или даже списки обновлений не тянет. А так, чтобы показать возможность, но не обновлять - оно не умеет. Надо для этого ставить 1 и 0 соответственно, но тогда оно начнёт жаловаться при обновлении пакета, мол, вы тут что-то наломали.

На уровне конфигов сейчас исправить тривиально, но подход непорядочный.
netch80: (finch)
Что трёх видов скобок не хватает языкам программирования - видно по такому извращению, как <> для шаблонов в C++, Java и прочих - проблемы парсинга тут известны каждому, кто интересовался.

Но на сейчас непонятно, почему останавливаться на ASCII, если юникод чуть более чем везде. Вот например есть ⦓⦔ (U+2993, U+2994). template⦓class T⦔ class Foo { ... };
И выглядит нормально, и парсинг тривиален.

Есть, конечно, ещё варианты ⁅⁆ ⌈⌉ ⌊⌋ ⦇⦈ ⸨⸩, но как-то менее выразительны...
netch80: (Default)
Случайно обнаружил существование в СССР понятия "отраслевая нормаль", которая "нормаль - это как стандарт. только нормаль". Определение не гуглится, отличия от стандарта (ГОСТ, ОСТ. ТУ) - тоже. Причём некоторые вводились в те времена, когда стандарты уже были.
Как-то загадочно.
netch80: (Default)
Если сделать все команды пятибуквенными, то можно после этого гордо говорить "да, есть режим [censored], но я не помню, какой пентаграммой его вызывать".
netch80: (finch)
В современной практике "проблема останова" теоретической CS чаще всего выливается в вопрос "а где на 3-м уровне вложенности ссылок репозиториев находится указание, откуда же берутся сорцы нужной тулзы".
netch80: (finch)
Для определённости, в 8 битах.
coding Значение 10000000 Значение 11111111
unsigned (беззнаковый) 128 255
sign-and-magnitude (прямой) 0 -127
1ʼs complement (обратный) -127 0
0ʼs complement (2ʼs complement, дополнительный) -128 -1
??? (обратно-дополнительный) -1 -128


"В железе" вроде были только первые три. (Сейчас реально встретить только дополнительный.) Четвёртого я не видел, хотя для полноты картины он должен был где-то возникнуть. Возник: CBOR, хоть это и чисто программное решение.

Кря. То есть, признаю неизбежное.
netch80: (finch)
History implementation in bash is really ugly.
This is where sqlite looks useful.

UPD[2025-02-06]: https://github.com/NorfairKing/bevel
netch80: (Default)
Как сделать установку нового диска в десктоп незабываемой от полного непонимания, что вообще творится и на каком свете находишься? Надо всего лишь просочетать несколько факторов:

1. Если диск не упомянут в пункте "Hard drive BBS priorities" в настройке BIOS, то та его не отдаёт в I/O через int 13h. В результате GRUB не может его увидеть.

1б. Первым в списке стоял тот диск, с которого не загружаются ;(

2. Простых надёжных способов собрать grub.cfg под новые условия (смена корневого раздела) нет, а замена UUID редактором не позволяет подсказать, что надо было ещё добавить "insmod part_gpt" (на старом такого не было).

3. На диске с GPT но без "BIOS boot partition" GRUB ставит свой core.img урезанным и неверно работающим. Но чтобы понять, что не так, его родной документации не хватает, там связь замолчана.

4. Если GRUB не нашёл по указанным UUID и пути типа (hd1,msdos5) раздела со своими модулями и конфигами, он хватает первый попавшийся, который нашёл.

4б. При этом он ещё перезаписывает UUID в параметрах загрузки, чтобы совсем уже никто не догадался.

5. Спросить, по какому пути GRUB прошёл и прочитал свои конфиги, откуда грузил модули - невозможно.

6. На то, загрузит ли BIOS внешнюю флэшку, если она была вставлена до перезагрузки, влияет погода на Марсе. Если нет - пункт в boot menu есть, но молча игнорируется.

Таки взлетел. Выдыхаю:)
netch80: (Default)
Есть виндовый лаптоп с 10кой. Как это принято у производителей лаптопов, в центре правой части стандартный numpad. Регулярно возникает ситуация типа нажимаешь Shift+PgUp - получаешь 9. Клавиши стрелочного блока есть, кроме Insert (злобный хьюлетт не сделал её даже как Fn+Del, хотя что им стоило), но расположены неудобно и непривычно. Диверсанты однако.
Поставил вопрос: хочу устранить логику "при NumLock=off, Shift+клавиша даёт цифру" (включая точку для Del).

Смотрел на Keyboard Layout Creator от MS - numpad там вообще не задействован. Смотрю в утёкшие файлы конфигурации стандартных раскладок - там эта часть вообще не настраивается. Похоже, логика стандартизована где-то в общем коде, не зависящем от раскладки :(

Попытался подвеситься на WH_KEYBOARD_LL. И тут оказалось, что не всё просто. Home стрелочного блока и Home цифрового блока даёт одинаково 36 (VK_HOME) при numlock=off. Home цифрового блока даёт 103 (VK_NUMPAD7) при numlock=on. Во flags таки младший бит даёт различие между двумя клавишами. Итого вариант, который вроде работает (проверил вживую): если вижу одну из 10 клавиш (центральная 5 не в счёт) и flags&1==0, ставлю 1 в младший бит flags и передаю дальше. Похоже на правду.

В Linux реализация заняла несколько строчек в конфиге, а тут - извращаться. Но победил.

Попутный вопрос: почему эта центральная 5 - VK_CLEAR в Windows и KP_Begin в XFree86? Откуда это и что должно было значить?
netch80: (Default)
Электроника местами настолько загадочная вещь, что хочется докопаться до причин именно потому, что не понимаешь, как такое могли получить. Вот есть банальная десктопная клава Sven 301 с USB интерфейсом. Цепляюсь через usbhid-dump и наблюдаю реакцию. Если одновременно придавить qwer и yuio, например, то через секунду оно начинает жаловаться на rollover error (далее ROE). А если qwer и uiop - не жалуется. Почему, чёрт возьми? Что за злобные дизайнерские изыски в столь банальном устройстве, зачем? Что виновато - хард или софт? И зачем оно ждёт секунду?

Если зажать sdf, то: wertgxcvb - любая из этих добавленная к sdf вызывает ROE. А вот a,q,z - не вызывают. Только не говорите, что проводки так идут:) wasd одновременно вызывают ROE. Явно не геймерское устройство:) А вот asdf - нет. Любая из dfg, fgh, ghj, hjk - да. jkl - нет. Чо?

(Ну да, мне было откровенно нечего делать. Но...)

UPD: секунду, а не полсекунды. Добавил второй абзац.

UPD2: Клавиша \| имеет код 0x2b в Set 1 и 0x5d в Set 2, единообразно. Но в USB это 0x31 на клавах где она в D13 (ANSI) и E13 (JIS), но 0x32 на ISO (позиция C12). Л - логика.
(Согласно HID tables это таки в USB две разных клавиши: Keyboard \ and |, и Keyboard Non-US # and ~. Но зачем, если они одновременно не встречаются?)
netch80: (Default)
Перевожу застарелый сишный код на C++. Самые неприятные чудеса:

1. Designated initializers - это типа struct moo { .a = 1, .b = 2 } - не поддерживаются, C++ сторона не смогла такое согласовать. Из g++ выкинули и ввели снова уже только ближе к C++20.
Приходится записывать все значения с их умолчаниями явно.
Попытался вырулить это через конструктор с параметрами - как-то не работает.
Самое неприятное, что на массив на полсотни таких структур жалобы идут на последнюю строчку всего массива - дальше разбирайся сам. Лечится через #if 0 и смещение его по мелким кусочкам.
1ʹ. Потерялась возможность писать конструкции типа sig_action = (struct sigaction) { .sa_handler = usr1signal };.

2. Если битовые маски были объявлены через enum, типа enum moo { COW = 1, DOG = 2 }, то в flags &= ~DOG; требуется раскрытие операции и явное приведение к moo в присвоении. Тут уже просто обидно (кажется, в C# пометив enum как битовые маски можно уйти от подобных проблем).

3. Инициализация структуры внутри другой структуры без квалификации области видимости. Основной туман возникает на записях типа LIST_HEAD(moo, moo_params) params.

4. Ну естественно куча присвоений типа frx = calloc(1, sizeof(*frx)). GCC добавляет сюда адресную арифметику для void*.
К calloc() ещё вопрос - если я перейду на new/make_unique/etc., memset вроде по-прежнему допустим, но некрасиво.

5. Ошибки типа "goto обходит инициализацию переменных, низзя!"

(Понятно, что это всё следы быстрого перехода и дальше будут вычищены. Речь не о том.)
netch80: (Default)
Внезапно озарило: на FreeBSD ещё надо было явно указывать при настройке включение NTP, сервера, стиль (рывком или нет) и т.д. - а на Linux этой привычки уже нет, обычно оно как-то само магически работает. В systemd вообще свой встроенный демон. Раньше тщательно тюнил набор серверов, сейчас надо постараться поискать, есть на это конфиг или нет, и как его писать. В облаках на старте системы гипервизор гарантированно даёт точное время...
Хорошо ли это, что точность времени перешла в категорию "воздух" - ресурс, который всегда есть? Что админы/девопы моложе ~30 просто не понимают, как его может не быть?
И чем time.constant.com из Ubuntu лучше pool.ntp.org?
netch80: (Default)
$ export F=`printf "\xff\xfe\xfd"`
$ python3 -c 'import os; print(repr(os.environ["F"]))'
'\udcff\udcfe\udcfd'
$ python3 -c 'import os; print(os.environ["F"].encode())'
Traceback (most recent call last):
File "", line 1, in
UnicodeEncodeError: 'utf-8' codec can't encode characters in position 0-2: surrogates not allowed
зачем ловить медведя, если потом он тебя не отпустит?
netch80: (Default)
https://github.com/greensoftwarelab/Energy-Languages
https://core.ac.uk/download/pdf/322933073.pdf
и так далее.

Вкратце: написав что-то на языках, которые не имеют даже JIT, вы убиваете экологию так, что Грета воет от зависти.

Хотя пока идёт криптошиза с выжиганием рынка видеокарт и дисков, это всё, конечно, ещё неактуально.
netch80: (Default)
Новая коллега осваивает работу с нашими продуктами. При этом у неё мак (целевая обстановка - Linux, полностью проверяется в виртуалке).
А у нас в репе в одном каталоге рядом registrar.cxx и Registrar.cxx.
Коротко:
1) head с явным указанием имени - показывает оба с разным содержимым.
2) ls пишет только один из них, Registrar.cxx.
3) "причем я клонила через XCode и в этой репе только с большой, а отдельно клонила через консоль и там только с маленькой"
"я хотела скопировать файл с маленькой буквы в папку где есть с большой, а он мне предложил его перезаписать"

В нормальных юниксах файлы не путаются. На винде хотя бы жёстко один файл. А тут то один, то два, и фиг поймёшь, от кого чего ожидать.

Переименуем, конечно, но повод обсудить в общем случае.

Стандартные аргументы в пользу регистронезависимости: облегчение человекочитаемости. Это миф: её путают с человекоозвучиваемостью. Регистр не должен быть важен, например, в имени человека (хотя и тут могут быть тонкости). Но я не знаю, в каком случае с экрана будет читаться что-то в шрифтах, которые не различают регистр. И совсем не понимаю, почему и зачем различие регистра считается важнее, чем 100500 других различий.

Почему такие FS различают «foo.docx», «foo.docx », «foо.docx» и «fo​o.docx» (кто увидит разницу?), но не различают «foo.docx» и «Foo.docx»? И что будет в случае İı (см. Turkey test)?

Или вот:

> А у винды есть таблица преобразований для того что бы большие и маленькие буквы не отличались и как прнято в Микрософт в разных местах эта таблица может отличаться. В консоли файл создаётся, а explorer — переименовать файл не может, то кавычки не такие и файл не найжде, то пробелы в начале или конце файла и амба.

В идеале работа с этими чудесами должна идти в userland... но если нет, то пусть политика для конкретного каталога отрабатывается где-то в ядре - но должна зависеть от параметров каталога, а не от текущей локали приложения, и должны быть средства получить базовую форму имени и сравнить алиасы.

Но что за повышенный бред на маке?

UPD: Выкатил статью также на Хабр.
netch80: (Default)
Всякие cv.notify() пробуждают одного ждущего. Всегда есть вариант notifyAll(), это понятно. Иногда есть вариант одним вызовом пробудить нескольких, это не очень понятно (ну разве что для случая одновременного добавления толстой пачки заданий в очередь). Но не видно другого: где-то важно пробуждение в FIFO порядке, а где-то полезнее в LIFO (особенно во всяких пулах нитей, когда лучше передать новую задачу самой последней из завершившихся - её состояние ещё закэшировано, и всё такое).

Ожидаю увидеть интерфейс типа:

notifyFirst(count = 1)
notifyLast(count = 1)
notifyAll()

но нигде такого не видел. Почему?

braces...

Sep. 22nd, 2020 06:50 pm
netch80: (Default)
Когда в C++ не хватило трёх видов скобок, на шаблоны применили <>. Выглядело в начале хорошо, но получилось в итоге ужасно (грабли парсинга знают все, кто писал на C++, C# и ещё куче потомков).
По-нормальному нужно наперёд придумать до десятка новых видов скобок и добавить их в Unicode, чтобы хватило на все извращения. Но нужен художник, чтобы придумать оригинально (в смысле отличия от букв-цифр, от старых скобок и друг от друга). У меня хватает фантазии только дорисовать колечки и завитушки.

Параллельно обсуждение в FB.
netch80: (Default)
https://www.linux.org.ru/forum/general/15876129

я этих авторов ядра честно не понимаю.

UPD: Широкая статья на Хабре: https://habr.com/ru/articles/587722/
netch80: (Default)
Обновление фряхи потребовало спецдвижений, ибо:

# df /
Filesystem Size Used Avail Capacity Mounted on
/dev/ada0s1a 771M 581M 128M 82% /

# ls -l /usr/bin/clang
-r-xr-xr-x 6 root wheel 70607108 Sep 5 00:02 /usr/bin/clang

===> usr.bin/clang/clang (install)
install -SCc -s -o root -g wheel -m 555 clang /usr/bin/clang
strip: creation of /usr/bin/INS@Mdos failed: No space left on device
install: strip command strip failed on /usr/bin/INS@Mdos

требовать двойного размера для strip от столь убойного бинаря это пять. косяков.

надо бы с ней радикально что-то решать, но лень и карантин...
netch80: (finch)
Убедился, что старое правило "своп не менее двух RAM" актуально и сейчас, и особенно для лаптопа, в котором всего 8GB оперативки. Было 8GB свопа, и я не успевал замечать, как всё выедалось браузерами и начинался тяжёлый OOM. С 24, надеюсь, тормоза придут раньше. Или при NVMe надо умножать на 5?

Это в продолжение предыдущей заметки про выжирание памяти... клин начинался таки с исчерпания свопа.
netch80: (Default)
На лаптопе открыть фейсбук почти гарантированно приводит к выжиранию всей памяти (даже OOM не помогает), так что сейчас стараюсь в него поменьше ходить. Единственная разница с домашним и рабочим десктопом - объём RAM: 8GB против 16 и 32. А цены на RAM не падают с 12-го года.
От того, что пишу на Питоне, начинаю чувствовать себя преступником.
netch80: (Default)
Consider a binary search tree (AVL, red-black, whatever). The goal "find the least key strictly greater than the specified one" ("upper_bound" in C++ STL, higherEntry//higherKey in Java, etc.) can be implemented in manner (Java-like pseudocode):

current = root;
bestsofar = null;
while (current != null) {
  if (example_key < current.key) {
    bestsofar = current;
    current = current.left;
  } else {
    current = current.right;
  }
}
// return for KV extracting
return bestsofar;


This can be improved with optimizations (e.g. C5 adds special processing case without comparings if found exact match), but the main principle remains that we use single pass from the root to a leaf.

But Java TreeMap implementation uses strange variant (the same at least in versions 8...13):

    Entry<K,V> p = root;
    while (p != null) {
        int cmp = compare(key, p.key);
        if (cmp < 0) {
            if (p.left != null)
                p = p.left;
            else
                return p;
        } else {
            if (p.right != null) {
                p = p.right;
            } else {
                Entry<K,V> parent = p.parent;
                Entry<K,V> ch = p;
                while (parent != null && ch == parent.right) {
                    ch = parent;
                    parent = parent.parent;
                }
                return parent;
            }
        }
    }
    return null;


so, in some cases it backtracks using "parent" link to find the place it started passing only left-side links before final right-side dead end. (Really, all 4 key-based inexact searches utilizes this way, with minor differences and mirrored conditions.)

What case is being optimized with this approach?
netch80: (Default)
Подумалось: R и Python, кроме прочих плюшек, выполняют роль "улучшенный Fortran, теперь с GC". Но что мешает добавить его в оригинальный Fortran, кроме консерватизма?
netch80: (finch)
Хочу странного.
Про виртуализацию в линии IBM S/370...zSeries говорят, что она имеет чрезвычайно мелкие накладные расходы и позволяет делать до 3-4 уровней вложенности без заметной просадки производительности.
Но не могу понять, как они этого достигают.
Документ "Principles of operation" свободно доступен, но именно эта тема превращается в "смотрю в книгу, вижу фигу" в завале подробностей глав типа "ASN translation".
Внятные описания стиля howto не гуглятся.
Или я не по тем словам ищу?
netch80: (Default)
Неожиданно споткнулся о NAME_MAX == 255...
По-моему, оно давно неадекватно.
netch80: (finch)
In kde plasma 5.8 the super/win key is also used to trigger the launcher, when pressed and released without combining it with another key. To disable the feature, put

[ModifierOnlyShortcuts]
Meta=

in ~/.config/kwinrc.

источник
netch80: (finch)
Раз в пятый, наверно, пытаюсь сделать что-то лёгкое пробное на bison+flex и обламываюсь на чудовищно путаной и неудобной реализации. Прямой рукописный парсер оказалось сделать легче.
Вот сейчас что-то такое написал, что flex сгенерировал файл со строками:

#line 346 "lexer.h"
#undef yyIN_HEADER
#endif /* yyHEADER_H */
UFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );


Кто такой UFFER_STATE и на ком он стоял?

(UPDATE: это получилось, если задать %option header-file, но не задать %option outfile. Но нигде не описано, что нельзя задавать только первый из них!)

bison не может в h-файле описать yylval. byacc не может описать в h-файле ничего, кроме кодов лексем - остальное, мол, описывайте сами.

Обоим bison и flex нельзя задать включаемые в этот h-файл строки, отчего, в частности, YYSTYPE или контекстный параметр парсеру надо или описывать одинаково в нескольких местах, или передавать void* и конвертить его в каждом месте использования. Причём они сами не включают нужное в выходные *.h, отчего их надо подключать только со своими источниками определений.

В доке flex сказано "читаем из yyin типа FILE*, вариантов нет", но чуть позже оказывается, что можно переопределить YY_INPUT. Извините, это была секция не туториала-букваря. Спасибо, что в нормальных stdio есть funopen() и fopencookie(), но кто кроме дедов об этом помнит?

Дефолтов для yywrap, yyerror не предлагается, хотя можно было уже давно придумать несколько типичных вариантов.

Bison с pure scanner передаёт параметр-куку всем функциям, кроме yylex(), которому она нужна больше остальных.

За один вечер можно наматериться на неделю.

UPD: победил. Но количество хаков, потребовавшихся, чтобы обойти недоработки и свернуть их с жесточайшего legacy, не радует.

дыбро

Nov. 10th, 2017 06:15 pm
netch80: (finch)
Немного IT-дыбра.

Обновил и подлатал представления о теме синтаксического анализа и вокруг. Общий вывод - всё достаточно грустно, разрыв теории с практикой достиг состояния "не сходятся, и всем пофиг". Все более-менее сложные реальные проекты творят нисходящий закат солнца вручную (Clang, Go...) или делают хитрые подпорки под относительно стандартные средства (как bison в GCC, но со специфичными C/C++ хаками, когда лексер смотрит в таблицы идентификаторов). Особенно "порадовало" Most vexing parse - после такого однозначно понятно, почему Go, Rust, Swift (и наверняка ещё много кто) взяли паскалевский порядок слов в определениях. (Напоминает конкуренцию SVO/SOV/etc. в живых языках и её последствия в виде позиции определяющего слова.) Или аналог для C# - когда парсинг конструкции вида f(G<1,2>(7)) зависит от достаточно "левых" признаков вроде следующих скобок.
При этом много голосов за "нематематичные" подходы вроде PEG (для которого фиг определишь в общем случае, написал конфликтную грамматику или нет - приоритеты и контекстные ограничения гарантируют разбор стандартных случаев, а там хоть трава не расти).

Обнаружил, что, несмотря на достаточно большой опыт в C/C++, не вляпывался до сих пор в самые мрачные варианты undefined behavior и его последствий, типа такого. И при этом никто не учит, что "here may be dragons" (целыми стадами) - например, Шилдт («C++ базовый курс») вообще ни слова, Страуструп - одно упоминание вскользь на 1000 страницах; в вузах тоже про это ни слова (по тому, как учили дочку); словно завеса умолчания, после которой вдруг встречаешься с последствиями, когда приступаешь к реальной работе. Как-то всё это странно. (Ещё ссылок, кому надо: 1, 2.)
Радует, что при всём при этом уже есть средства (как UB sanitizers) детекта заметного количества таких ситуаций (так что плотность их влияния на некорректность выходного результата становится ниже плотности влияния испорченной памяти).

Перевёл домашний настольник с FreeBSD на Linux. Причина - при переходе на 11ю фрю начало саморесетиться в произвольные моменты, но при реальной загрузке (два браузера) не жило больше 10 минут. На форуме не помогли, были только смутные обвинения видео в Haswell процессоре. Но умудрялось падать даже в Virtualbox, то есть видео ни при чём. Времени и настроения разбираться не было, так что привет, Kubuntu (такая же, как на работе и на лаптопе). Linux по крайней мере там работает :) но обидно. У фряхи было таки много мелких, но приятных удобств.

Осознал, что после превращения linkedin в обыкновенную соцсеть с лайками - присутствие на нём означает не только цель куда-то перейти, но и просто почитать что-то от коллег :) Для поддержки этой ситуации - начал закидывать такие же заметки на linkedin (на английском). Ну, начал - громко сказано :) но парочка есть ;)
netch80: (Default)
Некая спека говорит о типах данных

String: Alpha-numeric free format strings, can include any character or punctuation except the delimiter. All char fields are case sensitive (i.e. morstatt ≠ Morstatt).

Так всё-таки alpha-numeric или оно can include punctuation? Или вообще except the delimiter?
netch80: (Default)
Исходник:

bool FixMessage::isResendable() const
{
    unsigned type = getType();
    return type != FIX_MT_LOGON && type != FIX_MT_HEARTBEAT &&
           type != FIX_MT_TEST_REQUEST && type != FIX_MT_RESEND_REQUEST &&
           type != FIX_MT_SEQ_RESET && type != FIX_MT_LOGOUT;
}


Выхлоп gcc:

0000000000438570 <_ZNK10FixMessage12isResendableEv>:
  438570:       8b 4f 0c                mov    0xc(%rdi),%ecx
  438573:       b8 01 00 00 00          mov    $0x1,%eax
  438578:       83 e9 30                sub    $0x30,%ecx
  43857b:       83 f9 11                cmp    $0x11,%ecx
  43857e:       77 12                   ja     438592 <_ZNK10FixMessage12isResendableEv+0x22>
  438580:       b8 37 00 02 00          mov    $0x20037,%eax
  438585:       48 d3 e8                shr    %cl,%rax
  438588:       83 e0 01                and    $0x1,%eax
  43858b:       48 83 f0 01             xor    $0x1,%rax
  43858f:       83 e0 01                and    $0x1,%eax
  438592:       f3 c3                   repz retq 


Кто-то догадался, что сократить проверку диапазона близких значений вычитанием базы - отлично.
Беззнаковое сравнение результата вычитания - очень остроумно.
xor с rax, когда достаточно с eax - чего пытаются добиться?
Финальный and с константой - разве из предыдущих команд не ясно, что там останется один бит?

Считаем контрольную сумму:

unsigned checksum(const char *m_begin, const char *m_before_csum)
{
    unsigned csum = 0;
    for (const char *p = m_begin; p != m_before_csum; ++p) {
        csum += *p;
    }
    csum &= 0xff;
    return csum;
}


Генерируем с векторизацией. Не буду приводить всю сумасшедшую простыню, только основной цикл:

        pxor    %xmm0, %xmm0
        addq    %rdi, %r9
        xorl    %edi, %edi
        pxor    %xmm6, %xmm6
        pxor    %xmm4, %xmm4
.L9:
        movdqa  (%r9), %xmm3
        movdqa  %xmm6, %xmm1
        movdqa  %xmm4, %xmm5
        addq    $1, %rdi
        pcmpgtb %xmm3, %xmm1
        movdqa  %xmm3, %xmm2
        addq    $16, %r9
        cmpq    %rdi, %rdx
        punpcklbw       %xmm1, %xmm2
        punpckhbw       %xmm1, %xmm3
        pcmpgtw %xmm2, %xmm5
        movdqa  %xmm2, %xmm1
        punpckhwd       %xmm5, %xmm2
        punpcklwd       %xmm5, %xmm1
        movdqa  %xmm4, %xmm5
        pcmpgtw %xmm3, %xmm5
        paddd   %xmm1, %xmm0
        paddd   %xmm2, %xmm0
        movdqa  %xmm3, %xmm2
        punpcklwd       %xmm5, %xmm2
        paddd   %xmm2, %xmm0
        movdqa  %xmm0, %xmm1
        movdqa  %xmm3, %xmm0
        punpckhwd       %xmm5, %xmm0
        paddd   %xmm1, %xmm0
        ja      .L9


Кто может объяснить, чем нуль в xmm4 принципиально отличается от нуля в xmm6, и почему их нельзя было объединить?

В пропущенной части: до начальной границы 16 байт - короткий простой цикл по байту, но после последней такой границы - цикл развёрнут в 15 отдельных групп со сравнением в каждой на достижение конца входного массива.

Замена char на unsigned char убирает только сравнения (pcmpgt*). Два разных нуля остаются.

За окном шёл снег и два нулевых регистра.
netch80: (Default)
Вот XKB весь из себя такой конфигурируемый в 10 слоёв абстракции, но что происходит при отработке Ctrl - зашито в код намертво:

char
XkbToControl(char ch)
{
    register char c = ch;

    if ((c >= '@' && c < '\177') || c == ' ')
        c &= 0x1F;
    else if (c == '2')
        c = '\000';
    else if (c >= '3' && c <= '7')
        c -= ('3' - '\033');
    else if (c == '8')
        c = '\177';
    else if (c == '/')
        c = '_' & 0x1F;
    return c;
}


и в этом есть несколько совершенно неожиданных вещей (например, почему "забой", который 0x7f и традиционно передаётся как ^?, они сделали ^8, а ^? даёт то же, что ^_ ?)

Похоже, это очередное место типа "40 лет назад сделали на 'отцепись', а теперь фиг поменяешь".

Да, и место, где эта функция, совершенно "ожидаемо" - XKBBind.c в libX11 (что в этой трансляции от слова bind?)
netch80: (Default)
После апгрейда убунты 14.04 -> 16.04, оказалось, залип pip2 в состоянии "я не знаю, что тут у вас, но я хочу версию 1.5.4, и идите к лешему".
После ручной замены на актуальную (8.1.1) в его стартовом скрипте - он даже дал себя проапгрейдить реально и заменил этот скрипт на такой, где версия не вшита.

Что полечилось - хорошо, но такой стиль бутстрапинга как-то смущает задним числом.
netch80: (Default)
Я понял, какой программе переписка на Go безусловно на пользу: это systemd-init.

Вторым должно пойти /rescue/* из FreeBSD. И, в принципе, на этом список кончается :)
netch80: (Default)
Программа:

#include <math.h>
#include <mpfr.h>
#include <stdio.h>

double fpu_sin(double x) {
  double r;
  r = sin(x);
  return r;
}

int main() 
{
  int i;
  int cd = 0;
  for (i = 0; i < 3000000; ++i) {
    double x = i * 1.0e-6;
    double r1 = fpu_sin(x);
    double r2;
    mpfr_t mx, mr2;
    mpfr_init2(mx, 53);
    mpfr_init2(mr2, 53);
    mpfr_set_d(mx, x, MPFR_RNDN);
    mpfr_sin(mr2, mx, MPFR_RNDN);
    r2 = mpfr_get_d(mr2, MPFR_RNDN);
    mpfr_clear(mr2);
    if (r1 != r2) {
      printf("Mismatched: x=%.20lg(%a)", x, x);
      printf(" r1=%.18lg(%a)", r1, r1);
      printf(" r2=%.18lg(%a)", r2, r2);
      printf("\n");
      if (++cd > 10) {
        break;
      }
    }
  }
  return cd ? 1 : 0;
}


На glibc 2.23 расхождений нет, программа выдаёт пустой выхлоп.

На FreeBSD (10.3, amd64) их много, вот первые несколько:

Mismatched: x=0.00260599999999999981(0x1.5592d98bf7f06p-9) r1=0.00260599705034083228(0x1.5592c0359972bp-9) r2=0.00260599705034083185(0x1.5592c0359972ap-9)
Mismatched: x=0.0098189999999999996(0x1.41bfbdf090f73p-7) r1=0.00981884222127722001(0x1.41be6b1ccbce4p-7) r2=0.00981884222127721827(0x1.41be6b1ccbce3p-7)
Mismatched: x=0.0187539999999999998(0x1.3343fa2ad3e92p-6) r1=0.0187529006832448421(0x1.333f5dc8f0659p-6) r2=0.0187529006832448386(0x1.333f5dc8f0658p-6)
Mismatched: x=0.0191819999999999977(0x1.3a4723aafff36p-6) r1=0.0191808236882919231(0x1.3a42349ce64acp-6) r2=0.0191808236882919196(0x1.3a42349ce64abp-6)


везде на 1 бит, но заметно.

Хм, я думал, что уж требования IEEE754 будут выполнять.
Или не верить MPFR? Это, кажется, уже перебор будет.
netch80: (Default)
Интересно и немного забавно наблюдать, как новые языки программирования разворачиваются от старой кондовой концепции "функция может возвращать только одно значение".

C сохраняет подход с единственным значением. Где нужно возвращать более одного значения - начинается передача по указателю (примеры на каждом шагу).

В C++ уже можно за счёт tuple делать возврат с распаковкой в набор переменных, хотя реализация этого на уровне ABI скорее всего идёт через структуру в памяти, а не регистры. Ну и передача по ссылке, конечно же, как косвенный метод (с затратами памяти).

Pascal - та же передача по ссылке.

Forth изначально не имел этой проблемы (хотя держание всего на стеке - само по себе источник тормозов).

В Java формально одно значение (возврат объекта, пока нет value types, слишком дорог, хотя JIT это может соптимизировать). В результате возникают ситуации типа возврата массивов, или битовых трюков (которые работают только потому, что нету типов целых беззнаковых; заметим, что в этой доке везде пишут -1-x, а не ~x - почему?)

В C# вначале сделали out-параметры (и, я считаю, требование писать out и ref в списке параметров фактического вызова - гениальное и чрезвычайно важное требование; Паскаль до этого не дошёл), теперь наконец добавили кортежи.

Fortran за счёт требования передачи по ссылке или входного-выходного копирования всех параметров решал это изначально (считаем, что аналог ref из C#) и даже чрезмерно (вспомним тему модификации константы).

Динамические языки (типа Python, JS, Erlang) возвращают по-прежнему одно значение, но за счёт того, что оно может быть кортежом (списком...), получается произвольное количество (за счёт затрат на распаковку) - не решение, но лёгкий обход проблемы.

Go, Swift, Rust - возврат нескольких параметров сделан изначально.

Но на уровне скомпилированного кода приходится ориентироваться на монстров компиляции C, так LLVM сделал возможность возврата нескольких параметров, а GCC - нет. Он тормозит всех. В результате в свежайших разработках типа RISC-V ABI имеем только одно возвращаемое значение (может растягиваться на два регистра, сути это не меняет). Не могу нагуглить, что мешает GCCʼшникам.
netch80: (Default)
Обновление Perl до 5.24 принесло, что defined() нельзя применять к массивам (уж не помню, для какой версии это рекомендовалось - чуть ли не 5.5, наверно), сломав скрипты домашнего mailnews. Фикс тривиален.

Зато на Centos 7 используется 5.14 - это ж в какой древности они его такой закрепили.
netch80: (Default)
Кого задолбали перепутанные кнопки мыши на скроллбарах gtk3 - лекарство.
Я с этим столкнулся, проапгрейдившись до (K)Ubuntu 16.04.

Процитирую, чтобы была копия.

Edit (or create) the file:

~/.config/gtk-3.0/settings.ini

And add the following:

[Settings]
gtk-primary-button-warps-slider = false

Идеального лечения всё равно не даёт (например, нажатие в любом месте длинной полосы текущей позиции - игнорируется, воспринимается только нажатие за её пределами), но уже кое-что.

Profile

netch80: (Default)
netch80

January 2026

S M T W T F S
    1 23
45678910
111213141516 17
18192021222324
25262728293031

Syndicate

RSS Atom

Most Popular Tags

Page Summary

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 23rd, 2026 01:44 am
Powered by Dreamwidth Studios