С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
Изначально было 2 перехода в отрицательной ветви и 3 перехода в положительной, здесь 1 или 2 перехода и нет пересылки, если JP Z выполняется после фиксированного числа итераций, то его можно вообще убрать. Вообще неплохо бы пояснить что это за код, потому что сейчас это что-то типа (A+B)/2 для старшей части и (A+B)/2^(128&(A^B)) для младшей, может здесь тоже что-то можно сократить.
Reobne(02.10.2019)
8-ми битное клиппирование по 0 для Y2
In:
DE=Y1X1 (заведомо находится в "видимой части" (D>0)
HL=Y2X2 (Y2 - заведомо находится за границей (H<0, L может быть как >0 так и <0)
Out:
DE - без изменений
HL - новые координаты (H=0, L - высчитывается этой самой попдрограммкой)
(решение о клиппировании/или не надо принимается ранее (по знаку H), это частный случай, остальные стороны клиппируются так-же)
Нарисовал-бы рисунок, но не знаю как вставлять сюда картинки (без танцев с бубном, хорошо-бы чтоб у нас как в ВК можно было, копи-пастом)
Но думаю и так понятно, "видимое" поле - это всё что попадает в положительный квадрант, остальное уже рассматривается и отсекается по нужной стороне.
Собственно потому и рассчитываются немного по разному средняя точка для X ил для Y - ибо у X учитывается полярность, а для Y она уже известно (D+,H-)
Всё сходится, бро, не забывай что координаты каждый раз новые, отрезок делится постоянно и в зависимости от того куда упало среднее (в + или -) - меняются точки расчёта, в конце-концов средняя оказывается в нуле (по Y) что и требуется.
Последний раз редактировалось Destr; 02.10.2019 в 12:38.
blackmirror(02.10.2019), Reobne(02.10.2019)
Проверка на 0 понятна, а зачем проверяется чётность?
Чётность?
Если ты про JP P, то путаешь видимо с JP PO(PE)
JP P,n - это переход если результат ПОЛОЖИТЕЛЬНЫЙ (PLUS)
Антипод - JP M,n (MINUS). Это флаг знака S (SIGNUM что-ли)
А флаг переполнения/чётности V/P, да, но в мнемониках путаница (только С и Z флаги "правильно" пишутся в мнемониках, C/NC-Z/NZ, а в остальном бардак)
Вообще косяков в мнемониках полно, тот-же ADD A,n (по идее ему быть ADD n ибо только к аккумулятору и применим, вот SUB n - "правильное")
Последний раз редактировалось Destr; 02.10.2019 в 14:04.
Отблин, как же тяжело на 10 языках сразу думатьи становится всё сложнее. Старею, что ли...
Ещё предложение. Считать не BC=f(DE,HL), а HL=f(BC,DE), и в одной из веток "LD DE,BC" заменить на "EX DE,HL".
И ещё:
не то же самое? Не совсем понял общий алгоритм, но примерно так:Код:add HL,BC sra H rr L
Код:PUSH DE JP PMID PMID_2 RR L PMID LD BC,HL ADD HL,DE SRA H JP M,PMID_2 JR Z,BZER ; jr быстрее jp, если переход не выполняется BPOS RR L LD DE,HL ADD HL,BC SRA H JP M,PMID_2 JP NZ,BPOS BZER POP DE RET
Последний раз редактировалось Bolt; 02.10.2019 в 16:59.
Destr, насколько длинные отрезки попадают на вход алгоритма? Если вычислять x=x1+dx или y=y1+dy, то dx или dy можно считать за 8 развернутых итераций как выражение A*B/C, где все числа беззнаковые и B<=C. Если A<=127 - в одной итерации будут 2 сложения с аккумулятором, условный переход и сдвиг для установки бита результата. Или можно использовать регистровые пары, если требуется A до 255, хотя цикл немного замедлится. Примерно по 30-35 команд в положительной и отрицательной ветке, и еще некоторое количество команд в ветке инициализации в которой B и C умножаются на 2, пока С<128, при этом такое же количество шагов будет пропущено в основных ветках. Или сотня команд слишком большая цена для оптимизации этого цикла?
Последний раз редактировалось blackmirror; 02.10.2019 в 21:17.
Про это думал, но оставил на потом, как явный вариант который будет применён когда уже остальное всё будет развёрнуто и избавлено от лишнего
Алгоритм простой:
0. В DE коорд.начала отрезка YnXn, в HL коорд. конца YkXk (известно что H<0)
1. Находится средняя точка отрезка (середина) Xm=(Xn+Xk)/2: Ym=(Yn+Yk)/2
2. Если Ym равен нулю - то это конец отрезка (YkXk=YmXm), клиппирование выполнено, RET
3. Если Ym<0 то XmYm - это новые координаты конца (YkXk=YmXm)
4. Если Ym>0 то XmYm - это новые координаты начала (YnXn=YmXm)
5. Goto 1
-128...127
Получается максимум: DE=#7f7f, HL=#8080, это длина отрезка= SQR(255^2 + 255^2)=360
Да небольшая, но пока не понял что ты предлагаешь.
Последний раз редактировалось Destr; 03.10.2019 в 08:14.
Если есть две точки (X1,Y1) и (X2,Y2) через которые проходит некоторая прямая, то узнать значение X для заданного Y чтобы точка оказалась на прямой можно по формуле:
X=X1+(Y-Y1)/(Y2-Y1)*(X2-X1), то есть фактически задача сводится к вычислению D=A*B/C. Далее некоторые рассуждения на тему того, как эти операции можно выполнить вместе без увеличения разрядности, но пока у алгоритма есть существенные ограничения по диапазону корректно обрабатываемых величин.
В развёрнутом алгоритме деления используется остаток S, который сдвигается с добавлением по 1 биту из A, если S<0, то к нему добавляется С, иначе вычитается, после чего частное сдвигается и к нему добавляется 1 если S>=0.
Для алгоритма умножения можно сдвигать B и если в перенос попадает 1, то добавлять к произведению A (здесь требуется увеличение разрядности).
Если объединить добавление A и С(или вычитание) из этих двух алгоритмов, то получается 4(на счёт 2х я ошибся) параллельные ветки по 8 итераций:
S<0, B>=128, нужно добавлять A+C
S<0, B<128, нужно добавлять С
S>=0, B<128, нужно добавлять -С
S>=0, B>=128, нужно добавлять A-C
Одна итерация в каждой ветке выглядит так:
сдвигаем B и затягиваем в него перенос полученный после сложения в качестве бита частного
если требуется, делаем переход в другую ветку
удваиваем сумму(из-за этого шага алгоритм деления не может работать с числами более 2^7, а использование A+C в суммировании уменьшает их диапазон вдвое)
добавляем константу соответствующую данной ветке
делаем переход в другую ветку, если знак суммы поменялся
Не факт что это будет особенно полезно применительно к отрезкам, но может у кого-то появятся другие идеи где это можно использовать.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)