Да здравствует препроцессор C!

В журнале «Наука и жизнь» в конце 80-х печатали статьи по программированию. Как-то было опубликовано замечательное предложение определить в C такие вот макросы:


#define BEGIN {
#define END }

и после этого писать, как на богомерзком Паскале. А вот сегодня нашел логичное продолжение этого подхода:


// Находим среднее арифметическое
срака посередине стало шняга кагбэ ХУЙ да;
туды_сюды в_общем какая_то козёл стал норма; козёл почти фигня; козёл и_ещё_больше ну
начал
посередине присобачить шнягу кагбэ козёл да;
Подрыхнуть в_общем чуть_чуть ну;
кончил
посередине стало посередине хуякс фигня;
Слышь_это "\n\nСреднее арифметическое элементов массива: " эээ посередине эээ бля;

Надо применить такой подходец на практике, надо.

В защиту аналитической геометрии

Подкинули ссылку на статью Андрея Панова в «Ведомостях» по поводу того, что в наших ВУЗах называется «высшей математикой».

http://www.vedomosti.ru/newspaper/article/2010/07/22/241292

Автор утверждает, что:

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

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

аналитическая геометрия … даже в курсе мехмата выглядит как трогательный рудимент

Вот насчет этого трогательного рудимента я и хочу высказаться. Что такое «ангем» на мехмате (на первом курсе, кстати говоря)? Это декартовы координаты на плоскости и в пространстве, скалярное и векторное произведения, уравнения прямой и плоскости, аффинные преобразования, немного — о проективных координатах и проективных преобразованиях, наконец, классификация кривых и поверхностей второго порядка.

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

http://pshenichny.livejournal.com/26954.html

Или вот с этой (секция «матемачиха и линейное щастье»):

http://blog.gamedeff.com/?p=64

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

Мне лично интересно: если начать обучение на мехмате сразу с линейных и гильбертовых пространств произвольной размерности (и не упоминать даже про R^n), кто после этого всего сможет сказать, откуда «растут ноги» у скалярного произведения (которое в произвольном гильбертовом пространстве считается «данным свыше» и никак не связано с длиной отрезка в обычном понимании)? Конечно, это красиво с математической точки зрения, но все-таки необходимы и простейшие примеры, возникающие из того же ангема, тем более, что они имеют практическое применение (с которым выпускник мехмата вполне может столкнуться).

PS Кстати, пользуясь случаем, хочу пнуть Javascript (точнее, ECMAscript) за отсутствие там возможности определить нормальные классы с нормальным operator+. Приходится либо писать такие извращения:

a = new SFVec3f(a1, a2, a3);
b = new SFVec3f(b1, b2, b3);

c = a.divide(2).add(b.divide(4)).multiply(3);

Кстати, как называется такая запись? Есть «инфиксная»: с = 3*(a/2 + b/4), есть «польская» или «постфиксная», знакомая многим по программируемым калькуляторам: 3 a 2 / b 4 / + *, есть префиксная: * 3 + / a 2 / b 4, такое чудо я боюсь сравнивать с чем-то осмысленным.

…либо под каждый временный объект заводить переменную и писать так:

t1 = a.divide(2);
t2 = b.divide(4);
t3 = t1.add(t2);
c = t3.multiply(3);

Оба способа мне не нравятся, но ничего приличного сделать не получается :(

Про диалектический материализм и ПО для Android

Есть такая фраза, являющаяся непреложной истиной для каждого сторонника диалектического материализма — «Бытие определяет сознание». Естественно, всякие идеалисты используют противоположные вариант — «Сознание определяет бытие», после чего жестоко ругаются с материалистами.

А вот в разработке ПО, видимо, можно сформулировать аналогичную вещь: «Возможности железа определяют методику разработки ПО». Я об этом писал на примере Arduino, а вот еще пример, не менее поучительный. Недавно видел у [info]belnetmon ссылку на статью о разработке ПО для мобильной операционки Android. Что же нам в ней советуют?

Ресурсы нужно экономить.
Нужно мгновенно выдавать реакцию на действия и поддерживать обратную связь с пользователем.
Производительность приложения главная цель. Нужно постоянно в процессе разработки оптимизировать производительность, не оставляя эту работу на потом.
Нужно измерять время выполнения, протоколировать и анализировать ход выполнения приложения, узкие участки кода, возникновения событий, выделение памяти, время жизни объектов. Что не измеряется, то нельзя оптимизировать.
Избегайте создания лишних объектов.
По возможности делайте методы статичными.
Используйте прямой доступ к полям вместо методов посредников.
Используйте static final для констант.
Не используйте enum там, где достаточно обычной переменной целого типа.

Все это вытекает из возможностей «железа». Современные мобильники и КПК сравнимы по производительности с «персоналками» где-то десятилетней давности (причем очень «грубо» — например, над 24 доступными для процесса мегабайтами ОЗУ в 2000-м году посмеялись бы). Вспомним, что происходило в программировании в те далекие времена.

Бывшие паскалисты (спасибо дядьке Фаронову!) успешно освоили «программирование мышкой» в Delphi. Сишники разделились на два лагеря — первые вслед за паскалистами поклялись в вечной любви к фирме Borland и пользовались CBuilder, вторые забыли TurboC, как страшный сон, и переметнулись в стан любителей Microsoft Visual Studio 6.0. С++ использовался в варианте «C on steroids» — слова «инкапсуляция», «наследование» и «полиморфизм» до многих доходили слабо, зато «заклинания» типа TForm1.OnClick() весьма понравились. Надо ли говорить, что полноценного стандарта C++ не было реализовано нигде, библиотека STL зачастую отличалась непредсказуемым поведением (например, в книжке Б. Кернигана и Р. Пайка «Практика программирования», вышедшей в 1998 году, приводится пример, когда один из Windows-компиляторов С++ был снабжен ужасно медленной версией входящего в STL дека), да и поведение компиляторов иногда оставляло желать лучшего (кто помнит, почему не стоит писать «for(int i=0; i < N; i++)" в VC++ 6.0?). Языки программирования, отличные от C и Pascal, в нашем Отечестве не котировались (по причине неведомо кем культивируемой веры в крутость русских программистов), а в Буржундии к тому времени уже по достоинству оценили хоть и более медленные, зато более "безопасные" Java и Visual Basic. Кстати, там же, в Буржундии, как раз к 2000-му году вылезли из своих нор мамонты и динозавры - знатоки FORTRAN, поправили где надо год и отправились на заслуженный отдых, пока им в аду прогулы считают. Замечу, что "интерпретируемые" языки, с "безопасными" типами, где программисту полностью закрыт доступ к опасным возможностям, появились лишь по той причине, что буржуины всегда умели считать деньги и прекрасно понимали, что дешевле нанять десяток индусов, чем двух сишников - больше шансов получить на выходе программу, не заваливающую систему два раза в час, да и следствие из закона Мура - если ваша программа тормозит, отложите выпуск - уже было взято на вооружение. С другой стороны, "Практика программирования" Кернигана и Пайка тоже написана не на пустом месте и не потеряла актуальность в начале 2000-х (а то и сейчас, во всяком случае, многие похапешники после нее будут плакать кровавыми слезами). Несмотря на все замечательные возможности языков, очень большое внимание уделялось и производительности - часто даже в ущерб языковым возможностям (например, самописный hashmap часто оказывался существенно быстрее STL-ного, в результате чего мог считаться предпочтительнее). В общем, советы по программированию для Android лишний раз напоминают, что удобные возможности языка и среды выполнения зачастую сильно влияют на производительность программы - причем зачастую отрицательно. PS А вот более развернуто мое мнение про Arduino: http://community.livejournal.com/ru_radio_electr/759218.html?thread=12768946

Еще за VRML

Надежда отечественного геймдева [info]golergka как-то спрашивал в комментах, зачем нужны VRML-ные извращения. А я сейчас на наглядном примере покажу, зачем.

На данный момент «мейнстримом» в плане динамического контента в вебе является Adobe Flash, правда, с начала 2000-х сильно сдавший позиции в пользу более универсального Ajax. Во всяком случае, извращения тех лет, вроде «сайтов целиком на Flash», встречаются реже и реже — «изобразительные» и «технические» возможности Flash теперь реализуют с использованием HTML, CSS и Javascript.

Единственная область, где позиции Flash до сих пор сильны — это динамическая графика. Если, к примеру, текстовую «мочиловку» такого типа:

И плодть его содрыгнулыся от боли, и страшные черные птицы обклювали иго со всех сторон…
А злой волшебник Хухур достал иликрическую пилу и стал, весело хохоча, отпиливать ему ногу и отпилил ее три раза! Воистину!..
И он, хохоча, откусил ему глаз…
Злая колдунья острым ножом разрезывала плоть жертвы…
Его жилы, хохоча, хрустнули под ударом стальной дубины, и кровь толстым потоком затопила Долину Смерти…
Воистину прольется кровь, ибо да будет так!!!

…думаю, этого достаточно — все же видели игрушки типа «Бойцовского клуба», где «мочилово» представляет собой длинный лог того, кто откусил кому яйца, в общем, если такую мочиловку попытаться снабдить графикой, то придется использовать Flash — нормальное рисование в Javascript+HTML совершенно недоступно (а когда все дойдут до поддержки HTML5 и элемента Canvas — я не скажу, да и никто не скажет).

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

Конечно, трехмерная графика с «оперативным» рендерингом на ПК применяется уже лет 20, вспомним тот же Wolfenstein 3D или Doom. Математическая основа 3D-графики прекрасно известна, и реализация «софтверного» рендерера не должна вызывать больших проблем при использовании любого языка высокого уровня (хоть того же ECMAScript). Недостаточная производительность скриптовых языков уже лет пять как не является проблемой, в чем нас пытаются убедить «веб-программисты». Но это теория. А что мы имеем на практике? Для Flash существует десяток софтверных 3D-«движков». Как говорит про них Википедия,

Скорость работы перечисленных движков зависит от используемой версии Flash Player, но в целом пока не достаточно высока.

Естественно, верить википедии на слово не стоит, а лучше убедиться лично, что я и проделал. Думаю, [info]golergka прекрасно известна многопользовательская игра «Танки онлайн«, в 2009 году ставшая «прорывом года» в использовании Flash.

tanki

Немного поиграл в эту «техническую заслугу» отечественных флешеров. Как игра — вполне приятно, ничего против не имею. Но насчет поразительной 3D-графики — не соглашусь. Графика довольно примитивна и каким-то прорывом является лишь для браузерных игр. А достигается это просто невероятной ценой — на моей не особо «дохлой» машине загрузка процессора достигала, держитесь за стул, 60-70%. Неудивительно — уже лет 10-15 для обсчета сложных 3D-сцен применяют либо очень низкоуровневые языки (вплоть до «оптимизации» на уровне ассемблерных кодов), либо специализированные графические процессоры. Flash не имеет доступа ни к тому, ни к другому.

В общем, по уровню графики все это напомнило мне виденную еще в начале 2000-х «игрушку» с паровозиком, сделанную фирмой Parallel Graphics для демонстрации возможностей своего VRML-браузера.

parovoz

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

Для работы потребуется VRML-плагин, причем желательно — Cortona 3D Viewer. Скачать его можно на сайте производителя.

PS Не надо понимать эту запись, как «Flash говно, VRML форева». Просто мне хочется показать, что в разработке 3D-контента для веба существует не только современный мейнстрим (в виде Flash и софтверного рендера) и не только перспективные разработки (Silverlight, JavaFX), но и «хорошо забытое старое». Кстати, поддержка асинхронных запросов к серверу в VRML тоже была прописана в стандарте 1997 года (в виде функции CreateVRMLfromURL()), просто применений ей тогда не нашлось.

UPD Почему-то Parallel Graphics не любит браузеры, отличные от IE, хотя их плагин в них прекрасно работает. Видимо, срабатывают ограничения из начала 2000-х.

Ктулху фхтагн!

void Rlyeh
(int mene[], int wgah, int nagl) {
int Ia, fhtagn;
if (wgah>=nagl) return;
swap (mene,wgah,(wgah+nagl)/2);
fhtagn = wgah;
for (Ia=wgah+1; Ia<=nagl; Ia++)
if (mene[Ia]<mene[wgah])
swap (mene,++fhtagn,Ia);
swap (mene,wgah,fhtagn);
Rlyeh (mene,wgah,fhtagn-1);
Rlyeh (mene,fhtagn+1,nagl);
} // PH'NGLUI MGLW'NAFH CTHULHU!

Отсюда: http://www.bobhobbs.com/files/kr_lovecraft.html.

Make me unsee it

Приходится иногда сталкиваться в программировании с такими «костылями», что даже не знаешь, стоять или падать.

Вот, например, извращенная задачка в веб-программировании. Есть два сайта — один на ASP.NET под IIS, другой на PHP под Apache. Первый крутится по адресу, к примеру, http://webserver:80/, другой — http://webserver:8080/. Задача — на первом сайте есть ссылка, открывающая окошко со страничкой второго сайта, оттуда надо передать JavaScript-ом какие-то данные в родительское окно. Думаю, все видели вот такие «палитры», так что представить в состоянии.

Разница в том, что «палитра» расположена немного по другому адресу и может подпадать под блокировку «кроссдоменной» передачи данных. Причем самое интересное — это то, что каждый из трех популярных браузеров понимает «кроссдоменность» по-разному.

Internet Explorer всех версий вообще не делает различий между domain.com:80 и domain.com:8080. Соответственно, все работает правильно.

Firefox считает такие «домены» разными и по умолчанию блокирует передачу. Правда, спасает вот такое заклинание, произнесенное перед открытием «палитры» в родительском окне и в дочернем — до передачи данных:

document.domain = document.domain;

Смысл заклинания совершенно необъясним, поэтому «это нельзя понять, это надо запомнить».

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

Вопрос фанатам «альтернативных браузеров»: и чего же вы добились, обвиняя Microsoft и Internet Explorer во всех смертных грехах, начиная от монополизма? Похоже, только того, что в каждом из браузеров надо применять свои «костыли и подпорки», а любая программа на JavaScript начинается с разбора трех случаев.

PS К сожалению, ни прикрутить ASP.NET к Apache, ни PHP к IIS нереально — апачевский модуль для ASP.NET совершенно не хочет работать, а PHP-шная часть сайта существенно использует апачевские возможности по работе с .htaccess.

Про форматы файлов

Только наши отечественные разработчики в ответ на предложение переделать доисторический бинарный формат файла в что-то более современное на основе XML могут заявить, что потеря одного байта в XML приведет к ВСЕЛЕНСКОЙ КОТОКЛИЗЬМЕ (предположим, что враги сперли вот такую скобочку: < — и тогда мы все умрем, адин-адин-адин), а уж их-то бинарный формат от такой неприятности защищен. Ага, от потери байта медным тазом накроются все таблицы смещений в файле, и мы даже не заметим этого, потому как ихнее глючное поделие регулярно вылетает с такими ошибками.

А может, этим деятелям хочется привязать народ к своей софтине — ведь XML в определенном смысле самодокументирующийся, в отличие от. Главное — не раскрывать (всех) секретов своего глючного формата, хе-хе. Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious.

PS Все надежды жадных до денег разрабов (да-да, документация «без гарантий совместимости с последующими версиями» за бабло) перечеркивает WinHEX. А кроме того, умение с умным видом смотреть на файл в шестнадцатеричном виде вызывает неподдельное уважение у всяческих PHP-программистов, особенно если сопровождать сей процесс высказываниями: «ага, это у нас 16-битное целое» :)

Про одно маленькое извращение

Посетители интернетов «со стажем», наверное, помнят про язык VRML, появившийся еще в 1997 году и позволявший описывать трехмерные пространства в «читаемом» виде. Практически для каждого браузера существовали плагины, позволявшие встраивать окошко с 3D-контентом на HTML-страницы. Даже я в далеком 2002 году не остался в стороне от использования VRML на домашней страничке и нарисовал в нем какое-то подобие сортира или станции метро «Кузьминки» — почему-то мне очень понравилась текстура кафельной плитки в каком-то VRML-редакторе.

Почему-то совершенно незамеченной в то время осталась возможность VRML-плагинов взаимодействовать со страничкой, в которой они находятся. Web 1.0 тихо исчез, уступив место для динамических сайтов с JavaScript, DHTML и AJAX (все эти три слова означают примерно одно и то же, разница в гламурности). VRML вообще не отличался особыми красотами, анимация там была в зачаточном состоянии (ЕМНИП, делалась она средствами реализованного там же JavaScript, но писать всякие «эффекты» приходилось практически вручную), а о возможности изменения 3D-сцены по полученным откуда-то «снаружи» командам никто не задумывался.

Теперь — о своем опыте прикручивания модного AJAX к немодному VRML. Конечно, можно было бы выбрать в качестве 3D-среды более современный X3D — дальнейшее развитие VRML, но для него попросту нет приличных плагинов для браузера. Для VRML я использовал Cortona 3D.

В общем, задача состояла в следующем. Есть трехмерная сцена с «лампочками», которые могут гореть, например, красным, желтым и зеленым — например, представим себе модель перекрестка со светофорами и база данных, даже проще — регулярно обновляющийся XML-файл, в котором записано, каким цветом горит какая «лампочка». Надо, чтобы трехмерная сцена динамически изменялась, отслеживая изменения в XML-файле, и при этом не требовала никаких действий от пользователя.

Естественно, задача очень легко решается, если отказаться от использования всяких VRML-ных хитростей, а сделать все с использованием обычного HTML и AJAX. С другой стороны, можно управлять VRML-сценой через JavaScript в браузере. Почему-то эта возможность VRML используется настолько редко, что о ее существовании в рунете не упоминают, а в буржуйских интернетах удалось найти лишь перепевы курсовой работы по программированию в университе Нэпира, что находится в доброй старой Англии. Надо ли говорить о том, что про объединие AJAX и VRML не написано вообще ничего? Решается же вышеописанная задача буквально парой десятков строк кода.

Конечно, можно решить ту же задачу тысячей разных способов. Например, можно отображать трехмерные объекты с использованием Flash. Можно использовать не VRML и не V3D, а какой-нибудь гугловский O3D или даже COLLADA. Пожалуй, всерьез использовать это могут только разработчики браузерных говноигр. Кстати, графика в современных VRML-плагинах вполне «на уровне» и не уступает многим более серьезным играм. Ну что, как насчет Lineage прямо в браузере?

PS Кстати, Cortona3D не работает с примером Turtle Graphics. Там требуется совсем небольшая доработка, но раскрывать этот маленький секрет я пока не буду.

Мифический Arduino-месяц

Прочитал недавно известную книгу Ф. Брукса «Мифический человеко-месяц». А сегодня в комментариях у [info]bitoniau увидел довольно распространенное мнение — мол, известная демоплата Arduino не нужна, можно собрать то же самое «ручками», то есть съездить в «Чип-и-Дейл», купить паяльник ватт на двести, припой — лучше всего ПОС-40, флюс — канифольку смрадную, текстолит гетинакс, хлорное железо, микроконтролер, горсточку бракованных деталей, набор тупых мелких сверл, затем загадить мерзким раствором пол-квартиры, взять паяльник за «не тот» конец, собрать программатор, плату с микроконтролером, потом поставить на компьютере AVRStudio, WinAVR и еще кучу всякой дряни, сжечь LPT-порт при прошивке — и все это только для того, чтобы поморгать диодиком. Мало кто сейчас следует книжке Борисова и тренируется «на кошках», то есть на выпаянных неизвестно откуда КТ315. А зря, ибо когда Борисов начинает рассказывать о цифровых микросхемах (и на этом, кстати, книжка уже почти заканчивается), «юный радиолюбитель» превращается в закоренелого паялу, а для такого запаять 24-ногое чудо враждебной техники — раз плюнуть.

Казалось бы, чего общего может быть у умещающегося в одном DIP-корпусе микроконтролера и огромной IBM System/360, занимавшей несколько шкафов и жравшей немерянное количество электроэнергии, и какое отношение книга Брукса может иметь к «единоличной» разработке программ для МК? Дело не в том, что микроконтролер близок по своим «ресурсам» к «суперкомпьютерам» прошлых лет (System/360 всяко покруче будет!). Просто в те времена еще не было замечательных линуксов, работающих на кофеварках, и программы писались на сравнительно низком (не плохом, а приближенном к «железу») уровне. А особенно верно это для операционной системы совершенно новой машины — основываясь на опыте разработки которой, Брукс и написал книгу.

Вот один только абзац:

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

Этот опыт, однако, сослужил плохую службу при программировании новой машины. Лабораторные разработки, предварительные или ранние выпуски компьютеров не работают должным образом, не работают надежно и не остаются неизменными день ото дня. <…> И хуже всего неопределенность, лишающая стимула копаться в своем коде в поисках ошибки — ее может там вовсе не быть.

Программирование для микроконтроллерных систем — в чистом виде системное программирование для «новой машины». Да, микроконтроллер — довольно хорошо изученная и документированная штука, но вот трудность вызывает сборка «первой схемы», особенно, если это схема на МК. Разве может начинающий знать, что керамический конденсатор необходимо разместить как можно ближе к корпусу микросхемы? А то, что блокировочные конденсаторы для пары микросхем вовсе не стоит заменять одним, пусть даже и с емкостью, равной суммарной? А нюансы, связанные с подключением кварца?

Непонятно, почему «светодиодная моргалка», собранная «по всем правилам», не хочет работать. Дело ли в программе, в прошивальщике, в программаторе, в схеме, в монтаже — начинающему не понять. А применительно к AVR — вспомним хотя бы о «фузах», неправильной установкой которых так легко угробить контроллер (купленный, естественно, в единственном экземпляре).

Современный программист привык к тому, что железо всегда работает нормально, именно поэтому многие, спаявшие простейшую схему на МК, так никогда и не находят «соплю» между ножками. Демоплаты как раз и решают проблему с «нестабильностью» собранного новичком в «паяльном деле» «железа». Как минимум, повышается шанс запустить первую программу на нормально работающем «железе».

Касательно Arduino — лично я не вижу ничего особо выдающегося в этой плате. Разве что какой-то набор функций (своего рода «ОС») и Bootloader — вот и все, чем эта штуковина отличается от других плат. Ну и пиар, соответственно.

Для разговора про ардуиновскую «стандартную библиотеку» хочу вновь обратиться к истории. Технологии и методы программирования развивались в тесной связи с развитием возможностей «железа». Та же Simula оказалась невостребованной в конце 60-х — для тогдашних компьютеров более естественными оказались «процедурные» языки. Приведу маленький пример.

Для не очень хорошего программиста на Java или любом другом подобном языке вполне естественно написать что-то вроде:

var s = new String();

for(var i = 0; i < 100; i++) String += i + ",";

Кое-кто может сослаться на историю маляра Шлёмы, но речь немного не об этом, тем более что класс String можно реализовать и без недостатков сишных строк. Если кто-то, подобно тому не очень хорошему программисту, не читал книжек по Java или другим языкам со "сборкой мусора", то предлагаю проследить, что же происходит в цикле. При каждой его итерации создается несколько экземпляров класса String, которые не уничтожаются сразу после окончания вычисления (как в C++), а остаются в памяти.

То, что мы не заботимся о явном выделении памяти и ее освобождении, и называется абстракцией. Нас не волнуют такие вещи, как стек, страницы памяти и прочие малопонятные вещи. Даже мусор за нами должен собрать "сборщик мусора" (кстати, тоже сделанный в Simula).

Естественно, что за возможность написать код, наподобие приведенного выше, надо чем-то расплачиваться - а именно, ресурсами выполняющей эту гадость машины. Комфорт программиста, не заботящегося о "смысле", скрытом за легко читаемой строчкой, оплачивается памятью, тактами процессора и прочими ныне почти забытыми понятиями. Именно поэтому Simula и оказалась не нужна в 60-х. А вот разработанный практически в те же годы C оказался гораздо интереснее для компьютеров с очень сильно ограниченной памятью, да и на тех же AVR широко используется.

Похоже, то, что avr-gcc умеет компилировать и объектно-ориентированный C++, послужило поводом реализовать "объектно-ориентированную" стандартную библиотеку Arduino. Хоть Страуструп и утверждает, что "никакое языковое средство не должно приводить к снижению производительности программ, не использующих его", но из этого совершенно не следует, что реализованные с использованием ООП и без оного аналогичные функции будут работать одинаково.

Зато кому-то стало легче - не надо изучать такой непонятный RS-232, достаточно лишь написать Serial.println(15 - 10) :) А потом начинаются пляски с бубном около ООП-шных изысков, реализованных на неподходящей для этого системе.

PS Я ни в коем случае не утверждаю, что объектно-ориентированное програмирование, преобразование типов и прочие замечательные особенности соременных языков программирования - это "аццтой". Они действительно облегчают жизнь. Сборка мусора - это гораздо лучше, чем ручное управление памятью, примерно настолько же, насколько современная автоматическая коробка передач превосходит ручную. Только вот не надо пытаться присобачить "автомат" к "Жигулям" (за ссылку спасибо [info]onfall).

Ненависти псто

Писал сегодня некоторое «пояснение» к написанному мной куску программы. Пришлось немного «разъяснить» примененную в программе аппроксимацию, для чего в ворде (!), пусть даже 2007-м, была с трудом напечатана такая формула:

formula-word

Для того, чтобы напечатать эту формулу, мне понадобилось пять (!) минут — в основном ушедших на тыканье мышкой в панельку с «компонентами» формулы. Посчитайте, сколько времени займет печать такой строчки в TeX:

$$B = B_{11} \frac{x-x_2}{x_1-x_2} \frac{y-y_2}{y_1-y_2} + B_{21} \frac{x-x_2}{x_1-x_2} \frac{y-y_1}{y_2-y_1} + B_{12} \frac{x-x_1}{x_2-x_1} \frac{y-y_2}{y_1-y_2} + B_{22} \frac{x-x_1}{x_2-x_1} \frac{y-y_1}{y_2-y_1}$$

А теперь давайте обозначим дроби \frac{x-x_2}{x_1-x_2} и \frac{y-y_2}{y_1-y_2}, например, греческими буквами хи и кси. В TeX-е:

$$B = B_{11} \chi \xi + B_{21} \chi (1 - \xi) + B_{12} (1 - \chi) \xi + B_{22} (1 - \chi) (1 - \xi)$$

В ворде… В ворде предстоит долгое тыканье в меню вставки символа. Почему-то из всего греческого алфавита в «быстром доступе» находится 13 букв. Хорошо хоть, что тэта и эпсилон — в двух начертаниях. Выбор букв меня тоже удивляет.

В общем, даже это можно стерпеть. Раздражает другое. При перемещении слева направо по формуле типа x-x2 совершенно нелогично перемещается курсор. В общем-то, логика в этом есть, и я, как программист, ее понимаю. Формула просто-напросто разбита на подформулы, примерно так:

formula-tree

При нажатии курсорных клавиш происходит обход этого дерева. Фокус последовательно перемещается от левого x ко всей формуле, затем к «подформуле» из правого x и двойки, затем к правому x, затем к двойке. Если мне хочется нажать Delete, когда курсор стоит перед правым x, то удаляется не правый x, а вся подформула целиком.

Замечу, что если использовать «старые» средства ворда и сделать подчеркивание «шрифтовыми» средствами — subscript и superscript долгое время были в ворде чуть ли не единственными нормальными инструментами для ввода чего-то, похожего на формулы, то курсор будет перемещаться более логично, строго слева направо.

Мораль? Не надо в WYSIWYG-редакторе смешивать программное представление элементов с «графическим». Вопрос на засыпку: курсор стоит в последней строке таблицы, таблица представлена в памяти одномерным массивом (думаю, все представляют такой «метод» адресации — a[m*N+n]). Куда должен переместиться курсор при нажатии клавиши «вниз»?

Неправильный ответ — какая нам разница, в какой клетке какой строки стоит курсор? Просто инкрементируем индекс активной ячейки, как и в прочих случаях.

Правильный ответ один: никуда не должен перемещаться.

Правильный ответ два: в первую ячейку того же столбца таблицы.

Правильный ответ три: курсор должен переместиться наружу таблицы.

Не знаю, почему разработчики и тестировщики пользовательского интерфейса в Word 2007 не углядели страшной нелогичности в редакторе формул. Еще хуже — если такое поведение было прописано в спецификации. В любом случае, в систему для набора математических текстов Word не превратился.

Конечно, порадовала (наконец-то!) удобная система стилей и заголовков. Из малозаметного пункта на перегруженной опциями панели предыдущих версий Word стили превратились в едва ли не самый заметный элемент на «ленте». Я всегда подкалывал [info]vanchez, когда тот колупался в майкрософтском редакторе с его слабыми (если не пользоваться пресловутыми стилями) возможностями по созданию всяческих оглавлений, демонстрируя ему замечательные возможности LaTeX. А ведь возможности по созданию «логической» структуры документа были еще в Word 6.0 (кто помнит такую древность?), да и в руководстве Microsoft Press по Word 7.0 были описаны.

Причина незнания народа о том, что Word имеет функции текстового процессора, наверное, в том, что каждое руководство по Word начинается с базовых и необходимых функций, обрастает огромным количеством скриншотов, а затем, где-то на середине, его просто бросают читать. А вот любая книга по LaTeX скриншотов лишена полностью, и почти все успевают дочитать до описания команды \chapter.

Кстати, а кто до сегодняшнего дня знал о возможностях ворда по оформлению содержания? А кто пользовался?

Про «браузерное» ПО

Очень здорово написано по поводу гуглокалькулятора:

Для проведения одной элементарной операции с целыми числами задействуется огромное число компьютеров: начинается всё на локальном ПК с браузером, выполняющим сотни тысяч арифметических операций (аналогичных по сложности исходной операции) для формирования http-запроса; дальше работают десятки маршрутизаторов, пересылающих пакеты, каждый из которых опять же выполняет сотни арифметических действий; пыхтит коммуникационное оборудование на более низких уровнях модели OSI, и это оборудование тоже много вычисляет, упаковывая пакеты в каналах, кодируя и декодируя данные; лишь потом приходит черёд серверов Google, которые запрашивают базы данных (потому что всё равно идёт поисковая выдача).

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

В общем, как-то не впечатляют заявления гугля о том, что через десяток лет все ПО будет работать на стороне сервера, а работать с ним будут через браузер.

PS Кстати, если уж на каком-то девайсе смог запуститься интернет-браузер, то уж несложные программы могут выполняться на нем? Могут, естественно. А уж о критериях «несложности» можно подумать и самим. Для провоцирования срача скажу, что на 286-м можно развернуть почти полноценный веб-сервер, например :) Да что там 286-й, люди на PIC и AVR такое сооружают, что знатоки DOM, XML, COM, и прочих трехбуквенных технологий нервно курят в сторонке.

А вот накидайте идей

На днях я мучился с USB-устройством на V-USB, и обзавелся прекрасным набором разных «мониторов» и «снифферов» USB-шины. Для чего можно применить такую коллекцию? Среди всякого хлама обнаружился адаптер для авиамодельных передатчиков под названием RC Joystick Pro версии 2.2 производства «фирмы» ED&IGL Hobbies.

rcjoystickpro

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

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

PS Конечно, «вычислимый на МК способ» может оказаться весьма гнусным, например, XOR с трехбайтовой маской. В общем, попробую поперебирать простые варианты, типа перестановок байт/полубайт, а там видно будет. А может, единственный метод «хацкерской» разлочки — брутфорс, ведь проверочный код может быть прошит одновременно с серийным номером.

Забавный глюк

Вчера маньячил библиотеку libusb, точнее, ее версию для Windows. Столкнулся с забавным глюком: при установленных драйверах этой библиотеки при выключении компьютера вылетал в синий экран стандартный драйвер usbhub.sys. После синего экрана компьютер перезагружался и снова запускал винды. Крайне весело, особенно когда домашние призывают вырубить этот мерзкий ящик и наконец-то лечь спать (в 2 часа ночи).

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

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

Вопрос к программистам

Обсуждаем тут с [info]golergka систему App Store — эппловский магазин софта для яблофона. Суть моих претензий к этой системе состоит в том, что участие в ней для программиста сопряжено с совершенно кабальными, по меркам shareware, условиями. Распространение программы требует регистрации разработчика в iPhone Developer Program, которая стоит минимум 99 долларов в год. Комиссия Apple, взимаемая при продаже программ, составляет 30%. Программа может быть отклонена по множеству причин. Как утверждает Макс, все это делается для того, чтобы программы для iPhone удовлетворяли некоторым «стандартам качества». По результатам обсуждения мы пришли к выводу, что «стандарт качества» для программ сводится к «поставилась-запустилась-удалилась-систему-не-запортила».

Теперь собственно вопрос. Представим, что в России окончательно победил православный национал-коммунистический ядерный техно-фетишизм. В Москва-реке живут нано-крокодилы, вокруг растут пальмы, в небе летают дирижабли и мезосферные агрессоры, вместо окончательно разрувшившегося нового корпуса истфака МГУ построен Биореактор, где [info]hirou с академиком Петриком варят лекарство от бессмертия для кошек Куклачева, а лично вы разрабатываете Русскую ОС для Душевного Компьютера, предохраняющую жизнь пользователей от стрессов и депрессий(c). Для предохранения пользователей от стрессов нужно сделать интерфейс (не пользовательский, а системный, если че) установки программ и API со следующими свойствами:

— любая программа гарантированно устанавливается и удаляется, не запортив при этом систему
— всевозможные «временные файлы» и прочий хлам, создаваемый программой, может быть удален вместе с ней; после операций установка-запуск-удаление система должна возвращаться в первоначальное состояние
— существует механизм цифровой подписи программ, позволяющий проверить целостность и отсутствие модификаций в программе (добровольный и со множеством сертифицирующих центров — от Патриархии, до, к примеру, академика Петрика :) Представляю надпись на коробке с антивирусом Касперского: «Благословлено лично Патриархом» :) )
— попытки программы выполнить действия, характерные для вредоносных программ, могут быть заблокированы; заведомо вредоносные программы установить невозможно
— нельзя запустить программу, которая установлена не через данный интерфейс
— и последнее требование, отличающее данную защищающую от стрессов систему от App Store: вся эта штука децентрализована, позволяет получить дистрибутив программы из любого источника, а «гарантии» правильной установки-удаления осуществляются техническими средствами, без проверки человеком

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

Про вычислительную мощность

Развитие нынешней вычислительной техники идет по пути наращивания вычислительных возможностей в рамках существующей архитектуры – больше гигагерц тактовой частоты, больше операций в секунду, больше гигабайт памяти… Для чего нужны такие мощности применительно к «домашнему» персональному компьютеру? Для того, чтобы отрисовывать «окошки» Windows или просчитывать несложную логику в играх, вполне достаточно чего-нибудь наподобие первого «Пентиума», а то «четыреста восемьдесят шестого».

Будем считать, что все программы написаны «хорошо», никто не пытается производить сложные вычисления только по причине криворукости программиста (луч анального поноса посылается фирме Lotus). Тогда все задачи, требующие большого количества вычислений, разбиваются на две категории – «мультимедиа», то есть работа с графикой, видео, цифровым звуком, синтез 3D-графики и «действительно сложные задачи» — например, расчет индекса Доу-Джонса или цены на бананы в Гондурасе.

«Мультимедийные» задачи, можно сказать, естественны для домашнего компьютера. Конечно, я ни разу не сторонник той мысли, что домашний компьютер должен быть гибридом медиацентра и игровой приставки с выходом в Интернет, но возьмем это в качестве примера. Мало кто рассчитывает дома атомные бомбы, а вот посмотреть фильм или поиграть в Doom – милое дело. Давайте оценим сложность, к примеру, декодирования JPEG. Предположим, что все вычисления выполняются на обычном «универсальном» процессоре. Тогда достаточно оценить скорость выполнения двух наиболее сложных операций – «деквантизации», представляющей собой 64 умножения и обратного косинус-преобразования. Если косинус-преобразование ускорить тем же способом, что и в случае быстрого дискретного преобразования Фурье, то в конечном итоге для декодирования каждого блока 8×8 понадобится 106 мультипликативных и 42 аддитивных операции. Точно так же оценивается и количество операций при кодировании JPEG. Заметьте, что я намеренно считаю сложения и умножения «порознь» — умножение зачастую — гораздо более сложная операция, обычно занимающая намного больше тактов процессора.

Все широко используемые видеокодеки основаны на той же идее дискретного косинус-преобразования и «квантизации», поэтому оценки скорости этих операций дают нам представление о числе операций, необходимом для просмотра видео на компьютере. Понятно, что это – довольно требовательная к ресурсам задача. Например, на стоящем в моем ноутбуке Pentium M с частотой 1,7 ГГц просмотр DVD-фильма требует 30-50% процессорного времени. Стоимость «минимального» процессора, способного в реальном времени декодировать MPEG-2 (какой-нибудь Pentium III), получается довольно высокой (а если учитывать и «обвязку» в виде памяти и контролеров привода – очень и очень существенной). При этом кажется непонятным, почему китайский DVD-плеер может стоить менее 30$, а микросхема, используемая в нем в качестве процессора, стоит около 10$.

Дело в том, что совершенно необязательно считать «элементарными» операциями обычные арифметические операции. Если рассмотреть все то же косинус-преобразование с квантизацией как функцию, «входом» которой являются 512 бит (таблица 8×8 байт), и с теми же 512 битами на выходе, то можно составить ее таблицу значений. Можно составить, например, схему из функциональных элементов И, ИЛИ и НЕ, которая будет реализовывать эту функцию. Есть даже методы автоматического синтеза таких схем, например, асимптотически оптимальный (то есть строящий схему с довольно близким к минимальному числом элементов) метод Лупанова. Реализовав такую схему «в железе», например, как модуль процессора, получим возможность вычислить заданную функцию за один такт.

Конечно, пример выше – своего рода жульничество. Нам никто не разрешит использовать такое количество элементов, которое возникнет в рассмотренной выше схеме – ее сложность будет сопоставима с «полноценным» процессором. Практическая ценность его близка к нулю, и сравнима с таковой, например, у программы для машины Тьюринга или чего-нибудь Brainfuck-подобного. В реальности поступают проще. Достаточно легко, к примеру, реализовать любой конечный автомат. Кроме этого, можно разбить задачу на более простые операции с более простыми схемами. Таким образом можно упростить схему. При этом скорость ее работы все равно останется очень высокой. Например, сделанный «на скорую руку» JPEG-кодер на довольно простой и «медленной» ПЛИС фирмы Xilinx способен обработать в секунду порядка 3 мегапикселей (тактовая частота – всего 50 МГц), при этом он состоит примерно из 7000 элементов. Для сравнения, «универсальный» процессор Zilog Z80 состоял из 3500 элементов, но ни о каком JPEG-кодировании на нем речь даже не идет. Если же вместо ПЛИС использовать специально разработанную микросхему, то скорость повысится на порядок. JPEG-кодер (какой-нибудь Zoran COACH или Ambarella) в любом современном цифровом фотоаппарате-мыльнице способен за одну секунду обработать не менее 20-30 мегапикселей. Это сравнимо с производительностью Pentium IV, но на порядок выгоднее и с точки зрения стоимости (напрямую зависящей от числа элементов), и с точки зрения энергопотребления.

Все современные процессоры представляют собой, грубо говоря, калькуляторы. Конечно, и у них существуют инструкции, позволяющие быстро выполнять некоторые характерные для «мультимедиа» операции, например, набор инструкций MMX в процессорах персоналок. Тем не менее, крайне важно сохранить универсальность центрального процессора, не превращая его в начинку для фотоаппарата или DVD-плеера. Для таких вычислений, как матричные операции для 3D-графики или преобразование Фурье для кодирования графики, уже давно применяют и более специализированные процессоры – соответственно, видеоускорители или аппаратные MPEG-декодеры. Даже первые «Pentium», снабженные аппаратным декодером MPEG, были способны показывать фильмы с DVD или VideoCD. Стоит упомянуть и компьютеры Amiga, которые в начале 90-х были единственными «персоналками», способными обрабатывать видео – благодаря специализированным сопроцессорам. Тактовая же частота центрального процессора составляла всего лишь 14 МГц. Конечно, никто не запрещает использовать для тех же вычислений центральный процессор, но специализированные справятся с ними гораздо быстрее.

Собственно, использование сопроцессоров для некоторых сложных операций – давно не новость. Гораздо интереснее может выглядеть другая, менее очевидная вещь. Уже достаточно давно выпускаются ПЛИС – программируемые логические интегральные схемы, специальные микросхемы, состоящие из отдельных «кирпичиков», каждый из которых может быть элементом И, ИЛИ и НЕ. Связи между этими модулями задаются «прошивкой» микросхемы. Именно с использованием ПЛИС моделируются «заказные» микросхемы (тут передаю горячий привет [info]corvus_bkgk). В зависимости от «прошивки» ПЛИС может реализовывать самые различные функции.

Удивительно, но до использования перепрограммируемых ПЛИС в персональном компьютере «дошли» только у нас в России. Многие «спектрумисты» слышали про «клон» ZX Spectrum под названием Sprinter. На самом деле Sprinter – в корне отличающийся от Spectrum компьютер, способный только эмулировать последний. Более того, Sprinter может имитировать поведение несовместимых между собой «клонов», и может работать в «своем» режиме, превосходящем по возможностям любой другой Spectrum или его клон. Это достигается путем использования в качестве системной логики в этом компьютере нескольких ПЛИС, «прошивка» которых может заменяться «на лету», во время работы компьютера.

Довольно «объемистая» ПЛИС может выполнять функции, например, видеоускорителя, или декодера MPEG, и даже сопроцессора для любых других операций, например, криптографических. Конечно, использование ПЛИС в «персоналках» потребовало бы специальных библиотек, наподобие DirectX, но могло бы дать немалый выигрыш в вычислительно сложных операциях.

Не буду говорить об общей «кривости» архитектуры современного PC, состоящей преимущественно из тяжелого наследия уродца фирмы IBM и ночного кошмара фирмы Intel, не буду издеваться над тем, что самые современные процессоры состоят в основном из «костылей и подпорок» ради совместимости с Intel 8086, но замечу, что сейчас увеличение параметров процессоров происходит с большим трудом. Тактовая частота уже не увеличивается, растет лишь количество процессорных ядер на одном кристалле. Боюсь, что привычные нам «пни» уже достигли предела в своем развитии. Вполне возможно, что уже в недалеком будущем появятся первые «реконфигурируемые» вычислительные модули.

Кстати, на ПЛИС можно эмулировать и «обычные» процессоры. Например, уже существует несколько Open Source (!) реализаций все того же Z80. Интересно, чем будут мериться школьники на форумах, когда «апгрейд» процессора превратится в простое «скачивание» новой прошивки из Интернета?

Про стереовидео и AviSynth

Оценил возможности AviSynth по обработке видео. Например, вот так можно сделать анаглиф из интерлейсного стереоролика (с чередованием строк — левая-правая, левая-правая).

Clip=DirectShowSource("D:\My Downloads\The_French_Line_3D\VIDEO_TS\MJPEGexample.avi")

w=Width(Clip)
H=Height(Clip)

AssumeFrameBased(Clip)

Separated=Clip.SeparateFields()

Even=SelectEven(Separated)
Odd=SelectOdd(Separated)

Merge(ConvertToRGB(Even).RGBAdjust(0, 1.0, 1.0, 1.0), ConvertToRGB(Odd).RGBAdjust(1.0, 0, 0, 1.0))

Lanczos4Resize(W, H)

Levels(0, 2, 255, 0, 255)

На очереди — аналогичные скрипты для других форматов стереовидео.

И еще про GNU-лицензию

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

Существует такая замечательная GNU-программа, как AviSynth. Она позволяет манипулировать с видеофайлами при помощи не очень сложного скриптового языка. Например, вот так:

clip1 = AVISource("video1.avi")
clip2 = AVISource("video2.avi")

return interlaced_dissolve(clip1,clip2,30) # dissolve from clip1 to clip2 over 30 frames

function interlaced_dissolve(clip clip1, clip clip2, int iter)
{
clip1 = clip1.SeparateFields()
evn1 = clip1.SelectEven()
odd1 = clip1.SelectOdd()
clip2 = clip2.SeparateFields()
evn2 = clip2.SelectEven()
odd2 = clip2.SelectOdd()
evn = Dissolve(evn1,evn2,iter)
odd = Dissolve(odd1,odd2,iter)
return Interleave(evn,odd).Weave().DoubleWeave.SelectOdd()
}

Насколько богат возможностями такой «видеоредактор»? Наверное, в нем можно сделать с видео буквально все, что угодно — то есть он намного превосходит в этом плане обычные программы вроде Adobe Premiere. Удобно ли пользоваться таким «видеоредактором»? Для программиста — да, для видеорежиссера — нет.

Каким может быть выход? Достаточно написать «frontend», который позволил бы «программировать мышкой» — то есть среду наподобие того же Premiere, оперирующую с AviSynth-овскими скриптами. Но ни один программист, то есть GNU-разработчик, делать этого не будет — зачем извращаться с GUI, когда все можно описать в скриптах?

Собственно, эта «ориентированность на программиста» и губит немалую часть опенсорсных программ.

Новости вордпрессоводства

А как вам нравится показанная в ролике тема P2 для WordPress?

Лично у меня возникло ощущение, что это — попытка соорудить на вордпрессовском движке некое подобие «древовидного» форума. И лишний раз хочу заметить, что технически и блоги, и форумы, и социальные сети строятся очень похоже.

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

Решаем дифуры на PHP

Достаточно достать из коробки какой-нибудь Asus EEE PC, написать такой код в «блокноте»:

<?php
function f1($x, $y1, $y2){
return $y2;
}

function f2($x, $y1, $y2){
return (1-$y1*$y1)*$y2-$y1;
}

header("Content-type: image/png");

$st = microtime();

$image = imagecreate(640, 480);

$colorBack = imageColorAllocate($image, 0, 0, 0);
$colorFore = imageColorAllocate($image, 255, 255, 255);

imageFilledRectangle($image, 0, 0, 639, 479, $colorBack);

$x0 = 0;
$y01 = 0;
$y02 = 0.0001;

$h = 0.1;

while($x0 < 64){
$p11 = $h*f1($x0, $y01, $y02);
$p12 = $h*f2($x0, $y01, $y02);

$p21 = $h*f1($x0 + $h/2, $y01 + $p11/2, $y02 + $p12/2);
$p22 = $h*f2($x0 + $h/2, $y01 + $p11/2, $y02 + $p12/2);

$p31 = $h*f1($x0 + $h/2, $y01 + $p21/2, $y02 + $p22/2);
$p32 = $h*f2($x0 + $h/2, $y01 + $p21/2, $y02 + $p22/2);

$p41 = $h*f1($x0 + $h, $y01 + $p31, $y02 + $p32);
$p42 = $h*f2($x0 + $h, $y01 + $p31, $y02 + $p32);

$x1 = $x0 + $h;
$y11 = $y01 + ($p11 + 2*$p21 + 2*$p31 + $p41) / 6;
$y12 = $y02 + ($p12 + 2*$p22 + 2*$p32 + $p42) / 6;

$x0e = $x0*10;
$y0e = 240 - $y01*100;

$x1e = $x1*10;
$y1e = 240 - $y11*100;

imageLine($image, $x0e, $y0e, $x1e, $y1e, $colorFore);

$x0 = $x1;
$y01 = $y11;
$y02 = $y12;
}

$st = microtime()-$st;

imageString($image, 3, 10, 10, "Calculation time " . $st . " ms", $colorFore);

imagePNG($image);
?>

загрузить все это на какой-нибудь бесплатный хостинг, пользуясь стандартным консольным ftp-клиентом, встроенным в Windows — и наблюдать вот такую картинку (обратите внимание, что выдает ее php-скрипт):

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

А вот ZX Spectrum

Еще один график, на этот раз — построенный программой на Sinclair Basic.

Из-за ограниченных вычислительных возможностей ZX Spectrum пришлось обойтись построением графика «по точкам», но даже так на расчеты ушло около 3 минут. Сколько пишется программа — считайте сами, для меня наибольшей сложностью было работать с эмулятором, не имея под рукой раскладки «оригинальной» клавиатуры.

10 DEF FN F(X,Y,Z)=Z
20 DEF FN G(X,Y,Z)=(1-Y*Y)*Z-Y
30 LET X0=0
40 LET Y0=0
50 LET Z0=0.0001
60 LET H=0.1
70 INK 7
80 PAPER 0
90 IF X0 >= 64 THEN GO TO 280
100 LET P11=H* FN F(X0,Y0,Z0)
110 LET P12=H* FN G(X0,Y0,ZO)
120 LET P21=H* FN F (X0+H/2,Y0+P11/2,Z0+P12/2)
130 LET P22=H* FN G (X0+H/2,Y0+P11/2,Z0+P12/2)
140 LET P31=H* FN F (X0+H/2,Y0+P21/2,Z0+P22/2)
150 LET P32=H* FN G (X0+H/2,Y0+P21/2,Z0+P22/2)
160 LET P41=H* FN F (X0+H,Y0+P31,Z0+P32)
170 LET P42=H* FN G (X0+H,Y0+P31,Z0+P32)
180 LET X1=X0+H
190 LET Y1=Y0+(P11+2*P21+2*P31+P41)/6
200 LET Z1=Z0+(P12+2*P22+2*P32+P42)/6
210 LET X0E=X0*4
220 LET Y0E=88+40*Y0
230 PLOT X0E,Y0E
240 LET X0=X1
250 LET Y0=Y1
260 LET Z0=Z1
270 GO TO 90
280 BEEP 1,2

График более-менее совпадает с построенными в Qbasic и на ECMAScript:

spectrum-graph