LINUX.ORG.RU

Написал функцию, куда положить?

 ,


2

2

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

Что делает:
Cчитает уровень градиента в заданной точке. Задается A(x1, y1), B(x2, y2) - линия градиента, значения от 0 до 255. Также задается точка T(tx, ty) и считается значение градиента в этой точке.

Код:
http://paste.org.ru/?3ux5ln

Код без комментариев:

unsigned char GradientValue(int x1, int y1, int x2, int y2, int tx, int ty)
{
    if ((x1 == x2) && (y1 == y2))
        return 0;
    float AB_A = y2 - y1;
    float AB_B = x1 - x2;
    float NAB_A = AB_B;
    float NAB_B = -AB_A;
    float NAB_C = -NAB_A * x1 - NAB_B * y1;
    if ((NAB_A * x2 + NAB_B * y2 + NAB_C) *
        (NAB_A * tx + NAB_B * ty + NAB_C) <= 0)
        return 0;
    NAB_C = -NAB_A * x2 - NAB_B * y2;
    if ((NAB_A * x1 + NAB_B * y1 + NAB_C) *
        (NAB_A * tx + NAB_B * ty + NAB_C) <= 0)
        return 255;
    float Dx = (x1*(y2-y1)*(y2-y1)+tx*(x2-x1)*(x2-x1)+(x2-x1)*(y2-y1)*(ty-y1)) /
               ((y2-y1)*(y2-y1)+(x2-x1)*(x2-x1));
    float Dy = (x2-x1)*(tx-Dx) /
               (y2-y1) + ty;
    float AD = sqrroot((Dx-x1)*(Dx-x1)+(Dy-y1)*(Dy-y1));
    float AB = sqrroot((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    float Ratio = (AD / AB) * 255;
    return (unsigned char)Ratio;
}

Пример применения:

    int x, y;

    int basecolor  = SML_COLOUR_RED;
    int transcolor = SML_COLOUR_BLUE;
    unsigned char alpha;
    int colour;

    for (x = 0; x < 500; x++)
    for (y = 0; y < 500; y++)
    {
        alpha  = SmlGradientValue(50, 50, 450, 450, x, y);
        colour = SML_COL_MIX(basecolor, transcolor, alpha);
        SmlImagePixelSet(img1, colour, x, y);
    }

Результат:
https://dl.dropboxusercontent.com/u/31471800/p2p/grad.png

Перемещено mono из talks



Последнее исправление: inn (всего исправлений: 2)
Ответ на: комментарий от shamaz

То есть division by zero тебе лучше?

конечно. Лучше получить NaN, чем «результат», который к реальности никакого отношения не имеет. NaN это понятно — где-то ошибка. А вот если числа почти равны, то «результат» будет на несколько порядков больше/меньше, и ошибки «не будет».

emulek
()
Ответ на: комментарий от AIv

Деление за цикл он не вынесет скорее всего.

последние версии gcc у меня выносили в таких простых случаях как этот. Я сам охренел, если честно.

emulek
()
Ответ на: комментарий от emulek

да, если точки раскрашивать — разницы никакой. Но в других задачах возможны fuckup'ы. Вроде зарплаты в 100500 миллиардов рублей за месяц.

emulek
()
Ответ на: комментарий от emulek

Да ну это задротство. Нет их - и не надо. Не, ну вообще надо конечно, но не на этом форуме.

Тут одни клоуны и пидорасы (без обид, я тут сильно обобщаю).

shamaz
()
Ответ на: комментарий от Eddy_Em

Претензии не ко мне, codecogs такие гифы выдает. У меня фон серый, поэтому лучше видно.

да это я понимаю... надо бы imagemagick присобачить как-то.

dikiy ★★☆☆☆
()
Ответ на: комментарий от Eddy_Em

А можно дрочить ушами.

Вообще, явно, что функция используется через жопу, если ей давать x1 == x2 и y1 == y2, так как это линия, вдоль которой идет этот градиент, и она задается пользователем, а не получается в результате вычислений.

В общем, нормально всё написано в этом плане. Претензий тут быть не может (а к стилю могут быть)

shamaz
()
Ответ на: комментарий от Eddy_Em

а еще я помню видал тулзу, которая могла быстренько выплюнуть картинку из latex-кода. Весила около 500kB и не требовала никаких либ дополнительных. Вот ее бы прикрутиь вместо codehogs.

dikiy ★★☆☆☆
()
Ответ на: комментарий от emulek

Для этого надо как мин. заиндайнить функцию. Трудновато это будет для гцц если ее тушка в доугом модуле:-)

Особенно феерично это выглядит на фоне соседнего треда, где ТС особо изощренно менял два инта типа борясь за производительность.

AIv ★★★★★
()
Ответ на: комментарий от dikiy

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

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от shamaz

Тут одни клоуны и пидорасы (без обид, я тут сильно обобщаю).

да пусть будут... И те, и другие, и латех.

emulek
()
Ответ на: комментарий от emulek

Эта функция работает принудительно, без настроек. Пихаешь код формулы внутрь тегов "latex" и видишь формулу.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Нафига до NaN доводить, если можно fabs(a-b) сравнить с FLOAT_EPSILON?

потому-что если ты сравнишь с FLOAT_EPSILON, и получится «больше», а потом поделишь на это «больше», то результат у тебя будет НАМНОГО больше/меньше.

По уму нужно посчитать ABS(a-b), и сравнивать с a и b. Ну и делить на разность тогда, и только тогда, когда a и b сравнимы с ABS(a-b). Т.е. если ABS(a-b) не меньше a и b в 100*FLOAT_EPSILON раз, то ошибка у тебя будет не больше 1%. А по твоему методу ошибка может составить и 100500%.

Это конечно если деление у тебя одно. А у ТСа оно не одно, а три и два корня, и в цикле. Который выполняется 250 тысяч раз.

Видишь как плохо, когда нет мозгов?

emulek
()
Ответ на: комментарий от shamaz

Вообще, явно, что функция используется через жопу, если ей давать x1 == x2 и y1 == y2, так как это линия, вдоль которой идет этот градиент

эта дельта должна вычисляться вне цикла. Её не нужно было вообще в цикл пихать. А тем более в функцию, откуда её никакой gcc не выдернет даже с -O3. Надо было дельту считать снаружи, и тогда внутри осталось-бы только сложение/умножение.

В общем, нормально всё написано в этом плане.

типичный говнокод. Да, к сожалению — нормальный.

emulek
()
Ответ на: комментарий от emulek

Видишь как плохо, когда нет мозгов?

Вижу, сам с этой жопой в куде сталкивался. Пока допер, что к чему...

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от AIv

Для этого надо как мин. заиндайнить функцию. Трудновато это будет для гцц если ее тушка в доугом модуле:-)

да, я же говорю — не смотрел особо. Кто же знал, что всё так печально?

Особенно феерично это выглядит на фоне соседнего треда, где ТС особо изощренно менял два инта типа борясь за производительность.

это магия a+=b; и так далее? О да...

emulek
()
Ответ на: комментарий от Eddy_Em

Пихаешь код формулы внутрь тегов «latex» и видишь формулу.

дык ты запихал, а я почему-то не вижу.

[latex]\forall a \in \mathfrak{R}[/latex]

emulek
()
Ответ на: комментарий от emulek

Между прочим, на миллиарде итераций наносекундная оптимизация даст выигрыш в 1 секунду. А миллисекундная — уже в четверть часа!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

да с этим все сталкивались(кто хоть что-то делал)... А вот как назовёшь такого «говнокодером», так обиды, жалобы, мат из под шконкианонимуса...

emulek
()
Ответ на: комментарий от emulek

Ну, ХЗ. Я сам себя быдлокодером называю, т.к. программистом не являюсь и делаю все через жопу. И вообще, я все через жопу делаю. Но по крайней мере, делаю, а не жду благодати.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от emulek

эта дельта должна вычисляться вне цикла.

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

Я таки прав? Могу быть и не очень, так как я тут свой быдлокод пишу и отвлекаюсь на него

shamaz
()
Ответ на: комментарий от Eddy_Em

Между прочим, на миллиарде итераций наносекундная оптимизация даст выигрыш в 1 секунду.

между прочим, а кто тебе сказал, что она ДАСТ эту наносекунду? Вот например тот код, где int'ы свопяться a+=b — ты уверен, что будет профит? Всем(и компилятору тоже) известно про команду обмена, и любой компилятор(чуть-ли не с борланд си) свернёт t=x;x=y;y=t;в xchg x,y, спрашивается — нахрена? Всяко xchg выполняется как минимум вчетверо быстрее трёх команд! (начиная с iPentiumPro).

emulek
()
Ответ на: комментарий от emulek

Ой, я посмотрел его тему, когда всем ЛОРом искали уравнение нормали. OMG

shamaz
()
Ответ на: комментарий от Eddy_Em

Странно. У меня картинка отображается. Посмотри adblock.

1. у меня нет адблока

2. с адблоком оно бы ничего не показало, а у меня показывает так

[latex;]\forall a \in \mathfrak{R}[/latex+]

emulek
()

А если y1 == y2, что будет? Не деление на ноль? Лень разбираться, но по-моему если задавать прямые параметрически будет намного проще.

crowbar
()
Ответ на: комментарий от shamaz

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

ИМХО тут ошибка проектирования как раз в том и состоит, что «функция не знает». Должна знать. Думаешь зачем нужны матрицы 4*4 в 3D графике? Как раз для того, что-бы не считать всякую ерунду для каждой точки, а вынести все вычисления ЗА тело цикла. Тогда всю комбинацию вращений-перемещений объектов и точки наблюдения можно свести к ОДНОЙ матрице. Ну а здесь всё намного проще.

И да, вычисление корня тут тоже лишнее. Корень ВНЕЗАПНО тоже сводится к сложению/умножению. Нам не нужен сам корень, нам нужно приращение корня на этом шаге. Вот реализация: http://ru.wikipedia.org/wiki/Алгоритм_Брезенхэма#.D0.A0.D0.B8.D1.81.D0.BE.D0.... (блин, 1962й год, 50 с лишним лет прошло, а быдлокодеры до сих пор не в курсе)

emulek
()
Ответ на: комментарий от emulek

Ну, чем черт не шутит: щелкни "управление скриптами" в обезьяне, "настройки" → "редактировать скрипт". И проверь, есть ли там вообще что-нибудь про латех.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от emulek

Думаешь зачем нужны матрицы 4*4 в 3D графике?

Если честно, да незачем. Перемещение можно закодить отдельно, а вращать кватернионами. И того надо хранить 4 (поворот) + 3 (перемещение) числа вместо 16. Это к слову. Не, а чё, не так? Просто я ща как раз пишу рендерер и мне очень интересно, как надо.

Вот моё вращение с sse, покритикуй быдлокодец )

https://github.com/shamazmazum/voxvision/blob/rnd/src/vect-ops/vect-ops-sse.c

А так согласен

shamaz
()
Ответ на: комментарий от Eddy_Em

Между прочим, на миллиарде итераций наносекундная оптимизация даст выигрыш в 1 секунду. А миллисекундная — уже в четверть часа!

А на 10^20 итераций какой выигрыш будет!!! На самом деле, важно не сколько наносекунд ты выиграл в одной итерации, а во сколько раз ускорил код. Мой скромный опыт подсказывает, что наносекундный выигрыш будет получен при одной итерации занимающий типа 10нс, т.е. это 10% - об этом даже говорить лень. Вообще, любая оптимизация ускоряющая код меньше чем вдвое недостойна ни обсуждения, ни реализации;-)

AIv ★★★★★
()
Ответ на: комментарий от emulek

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

crowbar
()
Ответ на: комментарий от AIv

Ну, есть такое. Я когда переписал свой алгоритм из октавы на куду, получил увеличение производительности с пары недель до нескольких часов!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

небольшой патчик скрипта делает код хорошо выглядящим в теме блэк:

-                return head + "<img src=\"http://latex.codecogs.com/gif.download?"+
+              return head + "<img src=\"http://latex.codecogs.com/gif.download?\\bg_black "+
dikiy ★★☆☆☆
()
Последнее исправление: dikiy (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.