JP M,...
Вроде как ещё больше переходов стало
Спасибо, ребят, ща буду пробовать...
Вид для печати
Изначально было 2 перехода в отрицательной ветви и 3 перехода в положительной, здесь 1 или 2 перехода и нет пересылки, если JP Z выполняется после фиксированного числа итераций, то его можно вообще убрать. Вообще неплохо бы пояснить что это за код, потому что сейчас это что-то типа (A+B)/2 для старшей части и (A+B)/2^(128&(A^B)) для младшей, может здесь тоже что-то можно сократить.
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) что и требуется.
Проверка на 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 - "правильное")
Отблин, как же тяжело на 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
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, при этом такое же количество шагов будет пропущено в основных ветках. Или сотня команд слишком большая цена для оптимизации этого цикла?
Про это думал, но оставил на потом, как явный вариант который будет применён когда уже остальное всё будет развёрнуто и избавлено от лишнего
Алгоритм простой:
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
Да небольшая, но пока не понял что ты предлагаешь.
Если есть две точки (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 в суммировании уменьшает их диапазон вдвое)
добавляем константу соответствующую данной ветке
делаем переход в другую ветку, если знак суммы поменялся
Не факт что это будет особенно полезно применительно к отрезкам, но может у кого-то появятся другие идеи где это можно использовать.