Евгений Степанищев

Это персональный блог, который ведётся в режиме записок обо всём, что меня интересует. Пишу, по большей части, про историю и программирование.

42

Сегодня у меня день рождения. Мне сорок два.

Возраст ответа на главный вопрос жизни, вселенной и всего такого

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

  • прочитал 39 книг, это на три книги больше, чем в предыдущем году;
  • продолжил исследование кирпичных клейм — рассмотрел кирпич Летягина в Самаре, казанские НА, НБ, КЛЗ, ТБ и АК;
  • пока незаслуженно обхожу вниманием страховые доски — знаю четыре места, куда надо дойти с фотоаппаратом, но добрался только до одного;
  • внёс небольшой вклад в проект mozjpeg — теперь он нормально собирается под седьмую ЦентОС;
  • в очередной раз побывал в Самаре, съездил в четвёртый раз в Турцию;
  • попробовал в деле ассемблер процессора 6502 (когда-то он использовался в первом компьютере компании «Эпл»);
  • написал считалочку про пиво на языках «Эль-76», «Юᓂ곧⎔», «Zephir», калькулятора «DC», ассемблере процессора 6502, ;
  • раздобыл для музея вычислительной техники «Партнёр•01.01» и несколько допотопных калькуляторов (надо бы их сфотографировать, кстати);
  • впервые подключился к ФИДО, да-да, в 2019 году!
  • занялся патефоном дедушки жены, удалось найти очень хорошего мастера, который смог его восстановить;
  • запустил наш продукт под архитектуру POWER8, для этого пришлось изобретать нетривиальные способы сборки пакетов;
  • успешно прошёл курс университета Иннополис по алгоритмам машинного обучения;
  • выложил две части своих «дневников жизни», планирую заняться остальными;
  • пользуясь необычным обмелением Волги в этом году, погулял по показавшейся из воды старинной Казани и поучаствовал в миниэкспедиции военно-поискового отряда на болота в Спасском районе;
  • попробовал флоатинг, пока только часовую продолжительность, планирую расширить свой опыт до трёх часов;
  • журнал «Форбс» взял у меня интервью касаемо одного из старых проектов;
  • побывал в офлайн-лагере, опыт оказал на меня такое большое влияние, что я до сих пор не могу осознать его полностью;
  • двухлетние занятия в спортзале с тренером наконец дали, на мой взгляд, очень ощутимые плоды в плане реабилитации повреждённой когда-то на спортивной гимнастике спины;
13 сентября  

(A)

Увидел в тексте правительственной телеграммы непонятную штуку — букву «А» в скобках: «(А)».

По контексту догадался, что это «@», но не сразу понял откуда такое обозначение. Лишь чуть позже дошло, что «@» — «„а“ в кружке́ », кружок показали скобками, а так как в телеграмме всё набирается прописными буквами, то и получается такое странное сочетание знаков.

10 сентября  

Гиря братьев Рекшинских

Гиря в два фунта, изготовленная на заводе братьев Рекшинских

Недавно один из чердаков обогатил меня старинной гирей в два фунта (818 грамм, если верить нашим кухонным весам). С одной стороны у неё клеймо с весом («2Ф» — два фунта) и производителем («БР. Р», гирю выпустил завод братьев Рекшинских), с другой — изображение двух сторон медали, которую Рекшинские получили за свою продукцию в 1886 году на одной из выставок. На изображении аверса сокращённая надпись «За трудолюбие и искусство» и год получения медали, на реверсе — портрет Александра Третьего.

Поверочное клеймо, поставленное в 1908 году поверочной палаткой Нижнего Новгорода

Рядом с изображением медали легко заметить медную пломбу с цифрами, это поверочное клеймо — свидетельство об успешно пройденной поверке, способ борьбы государства с обвесом покупателей.

На странице 214 справочника А. И. Гуляева «Торговля и торговыя установленія» читаем:

Вновь изготовляемыя металлическія гири должны быть снабжены особою вывѣрочною пробкою изъ красной мѣди, для наложенія на нее клеймъ.

Поверочные клейма стали ставить на гири ещё в 12 веке, но до 1899 года в этом вопросе был полный бардак — поверка производилась нерегулярно, часто — единственный раз, в момент изготовления, пошлина за услугу была в каждом городе своя и так далее.

На моём фото поверочное клеймо образца 1907 года — тогда его изменили на торговых гирях с орла на инициалы императора («Н II» — «Николай Второй») и корону. Цифра под короной — номер поверочной палатки (отделения Палаты мер и весов, осуществившего поверку), а «08» — год проведения процедуры (1908).

В моём случае номер поверочной палатки — «6», это палатка Нижнего Новгорода, где и располагался один из заводов Рекшинских.

8 сентября   история   сокровища

Кирпич «АК»

Кирпичное клеймо «АК» по постели, найденный во дворе жилого дома

Пока был в отпуске, один из друзей прислал фотографию кирпича, который нашёлся во дворе его дома в Казани. Дом старинный, кирпич, по виду — тоже. Очень необычное место расположения клейма — на постели, это редкость, обычно они у нас на тычке.

На роль производителя у меня только одна кандидатура — крестьянин Алексей Калугин, кирпичный завод на Арском поле которого в 1894—95 годах упоминается в источниках. Завод основан в 1885 году, производил по 300 тысяч кирпичей и работало на нём девять человек.

Мениск

«Терапевтический справочник. Том второй», Саратовское государственное издательство, 1935, стр. 538

На «Реддите» вовсю обсуждают вещи, о которых узнали очень поздно. Я тут тоже кое-что узнал в 41 год.

Открытие недели  — мениск бывает не только в колене (и даже там их два)! Оказывается в человеческом организме менисков немало, кроме колена, они находятся так же в акромиально-ключичном, грудино-ключичном, лодышечном, кистевом и височно-нижнечелюстном суставах.

Кроме того, мениском называют несколько выгнуто-вогнутых и вогнуто-выпуклых хреновин вне человеческого организма. Например, линзы некоторых типов или особую форму залегания пород.

5 сентября  

99 бутылок: Zephir

69. Zephir — язык программирования, созданный для написания модулей расширения PHP и являющийся его сателлитом. Текущая версия (0.12.2) содержит несколько багов, с которыми пришлось столкнуться при написании программы. К счастью, перед компиляцией «Зефир» транслируется в Си, поэтому разобраться в происходящем труда не стоило.

Язык со сборкой мусора, использует как статическую, так и динамическую типизацию. Последняя необходима, например, для сохранения результата вызова пользовательских методов, похоже транслятор пока не умеет опираться на подсказку возвращаемого типа, поэтому требует в таких местах динамическую типизацию.

По синтаксису «Зефир» явный наследник ПХП, но выглядит почище — без «долларов» в именах переменных (которые многих раздражают) и скобок в управляющих конструкциях (из-за чего напоминает мне Гоу). Процедурное прошлое здесь почти не видно — многие функции на типами имеют объектные эквиваленты.

К сожалению, реализация языка пока сыровата — на первые баги я наткнулся в первые десять минут программирования, а сообщения об ошибке синтаксиса предельно лаконичны — показывается только строка, в чём ошибка заключается приходится разбираться самостоятельно.

«Песня о пиве» на «Зефире» выглядит следующим образом:

// Beer song by Evgeny Stepanischev
// song.zep
namespace Beer;

class Song
{
	private static function format(int bottles) -> string
	{
		string result = "";

		switch bottles {
			case 0:
				let result = "No bottles";
				break;
			case 1:
				let result = "1 bottle";
				break;
			default:
				let result = "%d bottles"->format(bottles);
		}

		return result . " of beer";
	}


    public static function sing() -> void
    {
    	int bottles = 99;
    	var botStr = self::format(bottles);

        while bottles > 1 {
        	echo "%s of beer on the wall, %1$s of beer.\n"->format(botStr);

        	let bottles--;
        	let botStr = self::format(bottles);

        	echo "Take one down and pass it around, %s on the wall.\n\n"->format(botStr);
        }

        echo "No more bottles of beer on the wall, no more bottles of beer.\n",
        	"Go to the store and buy some more, 99 bottles of beer on the wall.\n";
    }

}

Поскольку язык используется для написания расширений, а не самостоятельных программ, написанному выше надо помочь запуститься:

zephir build
php -d extension=beer.so -r 'Beer\Song::sing();'
5 сентября   99   программирование

PHP: доступ к приватным свойствам

Кинули ссылку на один из способов получения доступа к приватным свойствам в ПХП, тут создаётся функция, которая вызывается в контексте объекта с закрытым свойством:

function inspect_closure(object $o, string $p)
{
    return (function () use ($p) {
        return $this->$p;
    })->call($o);
}

Я решил вспомнить сколько таких способов вообще существует в ПХП.

Сначала, очевидно, на ум должен прийти рефлекшн, ведь он для этого и предназначен:

function inspect_reflection(object $o, string $p)
{
	$refClass = new \ReflectionClass(get_class($o));
	$refProp = $refClass->getProperty($p);
	$refProp->setAccessible(true);

	return $refProp->getValue($o);
}

Теперь экзотика. Например, мне вспоминается доступ через преобразование в массив, я о нём уже однажды писал. При преобразовании объекта в массив его приватные и защищённые свойства видны по специальным именам в полном соответствии с документацией:

function inspect_array(object $o, string $p)
{
    return ((array) $o)[
    	sprintf("\0%s\0%s", get_class($o), $p)
    ];
}

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

По сути — родственник предыдущего метода. При сериализации все закрытые свойства в объекте сохраняются под теми же специальными именами, что в предыдущем способе:

function inspect_serialize(object $o, string $p)
{
	$class = get_class($o);
	$serialized = serialize($o);

	if (preg_match("/s:\d+:\"\\0{$class}\\0{$p}\";([^;]+;)/s", $serialized, $m)) {
		return unserialize($m[1]);
	}

	throw new \UnexpectedValueException('Something went wrong.');
}

Конечно такую регулярку очень легко обмануть, более корректно было бы написать парсер, но для иллюстрации принципа, думаю, вполне годится.

2 сентября   php   программирование

HA

Сначала немного не по теме.

Все файлы на виртуалку я переношу через образ дискеты и перво-наперво несколько слов о том как создать образ дискеты на «Маке». Мне необходимо куда-то записать эту информацию, иначе она у меня постоянно теряется. Из командной строки это делается так:

dd if=/dev/zero of=floppy.img bs=1024 count=1440
diskutil eraseVolume MS-DOS VOLUME `hdiutil attach -nomount floppy.img`
hdiutil attach floppy.img

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

Как справедливо напомнили читатели в комментариях к моему эксперименту c ARJ, в 90-е чемпионом по сжатию был архиватор HA (с алгоритмом PPM). Он был очень медленным по тем временам (помню DOOM сжимался за часы) и поэтому не слишком распространённым, но я с ним сталкивался.

Успехи архиватора HA — 23,7% исходного объёма

Для тестирования я выбрал форк архиватора, с которым сталкивался во времена интереса к языку программирования Си-​-. Форк быстрее оригинала в 1,5 раза, впрочем, как оказалось, сейчас это вряд ли имеет значение — сжатие файла из вчерашнего теста заняло малозаметное время.

214962-байтный файл сжался в 51088 байт, это 23,8% от исходного объёма. Это лучше современного xz с его 25,4 процентами, но по-прежнему хуже архиватора Compressia с его космическими 20,6%!

1 сентября   ha   программирование

ARJ

Что-то меня потянуло на разную околокомпьютерную древность.

Пока экспериментировал с арифметическим кодированием, как-то сами собой вспомнились различные архиваторы времён ДОСа, но больше всего почему-то ARJ, который в «Иркеннефти», где я иногда в летние каникулы работал в детстве, называли «а-эр-йот».

Один из рассказов Анджея Земянского, сжатый «а-эр-йодом» в экране «Волкова Коммандера»

Захотелось его сравнить с чем-нибудь современным.

Скачал виртуальную машину с MS-DOS 6.22, установил туда ARJ 2.21 (это версия сентября 1991 года) и попробовал посмотреть насколько уменьшится один из рассказов Анджея Земянского — первый попавшийся текстовый файл, который был у меня на компьютере.

В итоге файл размером 214962 байт ужался до 67634, это 31,5% исходного объёма. Современный архиватор xz 5.4.2 на максималках (использует алгоритмы LZMA и LZMA2) ужал тот же файл до 54648 байт, это 25,4% исходного объёма. Вроде неплохой прогресс.

Архиватор 2003-го года уделывает современный xz, как Тузик грелку

Но потом я вспомнил, что где-то в сети существует таблица сравнения архиваторов за 2002-й год. Победителя нагуглить не удалось, зато архиватор «Compressia», который находится строчкой ниже, нашёлся на «ВебАрхиве». Он смог сжать тот же файл до 44361 байт, что составляет 20,6% исходного файла. А это архиватор 2003-го года (я скачал последнюю версию — 1.0b)!

Всё как обычно — есть популярные продукты, а есть почти неизвестные программы, которые в тёмном углу пилят какие-то одиночки. Любопытно — как обстоят дела в этом пыльном углу в этом году, каких успехов добились такие малоизвестные архиваторы?

31 августа   arj   программирование

JPEG: арифметическое кодирование

Редактор «ГИМП» умеет открывать джейпеги с арифметическим кодированием

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

Производители то ли осторожничают, то ли так и не сделали внутри своих продуктов некие абстракции, которые бы позволили быстро внедрять любые декодеры форматов.

WebP едва появился в большинстве браузеров, а уже предлагается добавить поддержку BPG и FLIF. На фоне этой всей движухи неясно почему почти никто не обращает внимание на арифметическое кодирование в старом-добром джейпеге.

Этот метод кодирования изначально был защищён патентами компании «АйБиЭм» и поэтому декодеры его не реализовывали, но несколько лет назад патенты истекли и теперь вполне можно было бы добавить его в браузеры, жаль, что пока никто этого не сделал.

Эксперимент по использованию различных оптимизаторов джейпега

Меня привлекают в арифметическом кодировании две вещи: почти моментальная скорость преобразования без потерь из «традиционного» джейпега и бо́льшая эффективность кодирования.

Для эксперимента я взял первый попавшийся джейпег, который лежал у меня в папке «Загрузки» и попробовал сравнить результат арифметического кодирования и другие методы оптимизации в различных сочетаниях. На скриншоте выше example0 — исходный файл, example1 и example2 — результаты арифметического кодирования, остальные файлы применением других оптимизаций.

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

31 августа   jpeg   программирование
Ранее Ctrl + ↓