Вход

Просмотр полной версии : Что такое тангенс и как с ним боротся?



Destr
20.10.2011, 22:47
Речь об ассемблере.
Как реализовать вычисление (не обязательно реалтайм, можно табличкой) тангенса от произвольного числа (байта)?
Вот синус-косинус - это легко, табличка размером 256 байт и ок.
Там всё просто, число диапазона 0 - 0.9 помноженое на 255 и так для всех значений байта (от 0 до 255).
А как с тангенсом быть?
Ведь уже к 1/8 круга (в миру = 45 градусов, в асме = 32 градуса) приобретает значение 1 (т.е. по-нашему 255) и дальше стремительно идёт в рост.

Кто знает как правильно обращатся с тангенсом?
(и желательно чтоб как с синусом, чтоб в 8 бит).

Help!

Опс! Забыл пояснить что не от лени дергаю народ, а поискал по zx-журналам, но что-то не нашёл ничего для асма по теме (для ЯВУ - нашлось)

Titus
20.10.2011, 22:48
Лучше сразу обрисовать, для каких применений, ибо универсальная вещь всегда более громоздкая, чем заточенная под конкретную цель.

Destr
20.10.2011, 22:49
Лучше сразу обрисовать, для каких применений, ибо универсальная вещь всегда более громоздкая, чем заточенная под конкретную цель.
Заточить под конкретную цель я и сам сумею (надеюсь), мне бы разжевал кто общий подход (как генерить, как хранить, какая разрядность процедур умножения/деления и т.д. нужна).
Т.е. как это всё юзается в демках и прочем, там где точность не нужна (хватает 1/256), а скорость - очень даже.

Titus
20.10.2011, 22:51
Заточить под конкретную цель я и сам сумею (надеюсь), мне бы разжевал кто общий подход (как генерить, как хранить, какая разрядность процедур умножения/деления и т.д. нужна).
Исключительно зависит от целей. Не хватает 8 бит, используйте 16. И т.д. все определяет задача.

Destr
20.10.2011, 22:54
Исключительно зависит от целей. Не хватает 8 бит, используйте 16. И т.д. все определяет задача.
Блин, ну давайте так:
Есть угол (байт, 0-255, это полный круг как принято на спеке).
Нужен от него тангенс.
Точность - такая-же как у 256-байтного синуса вполне устроит.
Что дальше?
Как его сгенерить? (возможен ли массив в 256 или всё-таки только 512?)
Как его взять (в смысле выяснить TAN(угол))?

Titus
20.10.2011, 22:56
Блин, ну давай так:
Есть угол (байт, 0-255, это полный круг как принято на спеке).
Нужен от него тангенс.
Что дальше?
Если вы хотите иметь тангенс в виде 8.8 (8 бит целое, 8 бит дробное), и потратить на него 16 бит, то делаете табличку на 512 байт, где и храните готовые тангенсы.

Destr
20.10.2011, 23:01
А как обычно такую таблицу делают?
Я пробовал на бейсике, но непонятно на что умножать.
Т.е. для синуса пойдёт POKE адрес+текущий угол,SIN(PI/128*текущий угол)*255
А для тангенса на что умножать?

Titus
20.10.2011, 23:05
А как обычно такую таблицу делают?
Я пробовал на бейсике, но непонятно на что умножать.
Т.е. для синуса пойдёт POKE адрес+текущий угол,SIN(PI/128*текущий угол)*255
А для тангенса на что умножать?
Если тангенс интересует, опять же повторюсь, в формате 8.8, то умножать следует на 256. Таким образом 1 станет равна 256. Двойка - 512 и т.д. Ну, а все, что привысит 255 будет равно 65535.
Не понятно, зачем это вам надо) В данном случае цель рождает предложение)

Destr
20.10.2011, 23:09
Не понятно, зачем это вам надо) В данном случае цель рождает предложение)

Вот это пробую, а там без тангенса никуда http://zxdn.narod.ru/coding/ig5ray3d.htm

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

Vitamin
20.10.2011, 23:11
Проблемы будут в точках 64 и 192 (по понятным причинам). 63/256 даст значение 40. Вполне хватит байта для хранения.

Destr
20.10.2011, 23:17
Проблемы будут в точках 64 и 192 (по понятным причинам). 63/256 даст значение 40. Вполне хватит байта для хранения.
Да, это я уже выяснил в ходе экспериментов :)
В этих точках один из катетов нулевой, т.е. исскуственно подставлять 1 (чтоб стал как тот что длинный).
Или любое из соседних значений (исскуственно заменяя угол ближним, чтоб деления на 0 не было).
На бейсике я это всё понимаю, а вот в асм перетащить не могу (ну не калькулятор ведь подключать пзушный или самому подобные дела громоздить).
Подскажите чуть-чуть как это в асме сделать чтоб решалось так-же как с синусом. Ну типа.
LD L,угол
LD H,старший байт таблицы тангенсов
LD A,(HL); А=TAN(угол)

Vitamin
20.10.2011, 23:18
Подскажите чуть-чуть как это в асме сделать чтоб решалось так-же как с синусом. Ну типа.
LD L,угол
LD H,старший байт таблицы тангенсов
LD A,(HL); А=TAN(угол)
Ну ты уже написал. В чем проблема-то?

Titus
20.10.2011, 23:18
Вот это пробую, а там без тангенса никуда http://zxdn.narod.ru/coding/ig5ray3d.htm

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

Там вроде конкретно написано, как:

Назовём вертикальное расстояние до сле-
дующей точки Ya, горизонтальное Xa. Будем
искать все горизонтальные пересечения. Ya
найти легко - это высота клетки (64 в на-
шем случае). Xa можно найти по формуле Xa=
=64/tan(угол луча). Разумеется, для Speccy
тангенс каждый раз считать накладно,но мо-
жно посчитать табличку для всех возможных
углов заранее. Для поиска вертикальных пе-
ресечений Xa равен ширине клетки, Ya = 64*
*tan(угол луча).

Destr
20.10.2011, 23:21
Ну ты уже написал. В чем проблема-то?
Проблема написать 8-ми битную табличку (я сумел только 16 бит).
Чтоб процедура вида HL=H*L могла в дальнейшем работать.
А не HLDE=A*DE например юзать.
Вот и ломаю голову как извернутся (иначе летит всё нафик, ибо громоздко и соотв. медленно.)

Vitamin
20.10.2011, 23:37
Проблема написать 8-ми битную табличку (я сумел только 16 бит).
Чтоб процедура вида HL=H*L могла в дальнейшем работать.
Не понял. У тебя сложности с генерацией таблицы? Или доступом к ней?

Destr
21.10.2011, 00:04
Не понял. У тебя сложности с генерацией таблицы? Или доступом к ней?
Бинго!
Оба вопроса в точку!

Хотелось бы чтоб табличка в 256 байт и чтоб операции с ней не превращались в IEEE.

Eltaron
21.10.2011, 00:10
Хотелось бы чтоб табличка в 256 байт и чтоб операции с ней не превращались в IEEE.
так просто оно в интервал 0..255 не влезет. Куча первых значений будут нулевыми.
может хранить как-то хитро? Значения в ячейках 0..63 сдвинутыми влево на 3 бита, 64..127 на два, 128..191 на один, а 192..255 не сдвинутыми. И после выполнения умножения результат сдвигать вправо на сколько надо.

Destr
21.10.2011, 00:21
так просто оно в интервал 0..255 не влезет. Куча первых значений будут нулевыми.
может хранить как-то хитро? Значения в ячейках 0..63 сдвинутыми влево на 3 бита, 64..127 на два, 128..191 на один, а 192..255 не сдвинутыми. И после выполнения умножения результат сдвигать вправо на сколько надо.
Я примерно так затык и понял.
Только подумал сделать по другому.
Составить тангес до тех пор пока он в 1 не превратится и дальше уже заморачиватся при вычислениях где знак поменять, где операнды местами перекинуть, где вообще нафик NEG глобальный всему и вся.

Но это по-моему как-то того...
Прошлый век что-ли...
Этим пусть Женя999 (или кто там ещё на бейсике? ALKO?) занимается.
Им будет интересно, а я как-то уже поиграл в 2+2 на 24 листа, хочу научится быстрому кодингу.

Titus
21.10.2011, 00:43
хочу научится быстрому кодингу.
Чтобы научиться быстрому кодингу нужно:
1) Хорошо представлять себе весь алгоритм в целом, причем не только математическую модель, но и всю суть происходящих процессов, потому что тогда, и только тогда вы можете крутить и вертеть им, как захотите, редуцируя, меняя, и т.д.
2) Находить баланс между скростью, точностью и универсальностью используемых математических функций. Ибо, любой универсализм ведет к понижению скорости.
3) Ну и хорошо знать ассемблер)

Destr
21.10.2011, 00:49
Чтобы научиться быстрому кодингу нужно:
1) Хорошо представлять себе весь алгоритм в целом, причем не только математическую модель, но и всю суть происходящих процессов, потому что тогда, и только тогда вы можете крутить и вертеть им, как захотите, редуцируя, меняя, и т.д.
2) Находить баланс между скростью, точностью и универсальностью используемых математических функций. Ибо, любой универсализм ведет к понижению скорости.
3) Ну и хорошо знать ассемблер)

Пункт 1 сразу отпадает, ибо я только ПЫТАЮСЬ этот алгоритм КАК-ЛИБО реализовать.
Пункт 2 вытекает из П.1, т.е. до оптимизации ещё не дошло (сперва надо заставить работать, потом прочувтсвовать и уже потом оптимизировать)
Пункт 3 - это вообще выше всяких похвал! Не одолжите-ли на время свой ЛАМОметр?

В общем хотел примеры и советы от людей которые решали подобные проблемы, а опять флуд у нас получился :)
(ну почти флуд)

Titus
21.10.2011, 00:50
В общем хотел примеры и советы от людей которые решали подобные проблемы, а опять флуд у нас получился :)
(ну почти флуд)
Я как раз рассказываю подход по существу. Я делаю так. Иначе не получается.

Destr
21.10.2011, 01:01
Я как раз рассказываю подход по существу. Я делаю так. Иначе не получается.
Ну тогда продолжаем.
Как-нибудь можно развернуть Ваше представление о проблеме?
Ну начав с таблички например?
Как бы Вы её сформировали?
(или может-быть "А Вы как её формировали когда нужно было?") ?

Titus
21.10.2011, 01:07
Ну тогда продолжаем.
Как-нибудь можно развернуть Ваше представление о проблеме?
Ну начав с таблички например?
Как бы Вы её сформировали?
(или может-быть "А Вы как её формировали когда нужно было?") ?
Тангенсом не пользовался.
А проблему решаю последовательно. Сначала смотрю, какая минимальная точность результата мне подходит. Если 16 бит, значит 16, если 8, значит 8. Потом уже исходя из этого делаю таблицу. 8-битную или 16-битную) Что тут непонятного?

Destr
21.10.2011, 01:14
А проблему решаю последовательно. Сначала смотрю, какая минимальная точность результата мне подходит. Если 16 бит, значит 16, если 8, значит 8. Потом уже исходя из этого делаю таблицу. 8-битную или 16-битную) Что тут непонятного?
Если не сложно - пожалуйста пример.
Либо код с комментариями, либо разжёвку как это сделать (ну по уровню как в zx-ревю "Программирование в машинных кодах и на языке ассемблера").
А если лениво OR некогда OR "просто-ты-дестр-рожей-не-вышел" = ну извиняюсь.
Мож кто ещё подскажет :)

Titus
21.10.2011, 01:28
Если не сложно - пожалуйста пример.
Пример чего, как из таблицы вынимать значения?



8-битная таблица:

LD H,База таблицы
LD L,Значение угла
LD A,(HL) - А - синус угла L

16-битная таблица:

LD H,База таблицы
LD L,Значение угла
LD E,(HL)
INC H
LD D,(HL) - DE - синус угла L

Destr
21.10.2011, 01:33
Пример чего, как из таблицы вынимать значения?
Да.
Спасибо.
Я так тоже умею.

МНЕ ИМЕННО ПРО ТАНГЕС!
С НИМ ТАКАЯ ТАБЛИЧКА НЕ ПОЛУЧАЕСТЯ!

Вопрос (в третий раз):
Как сгенерить такую-же (8 бит) табличку для тангенса?
Если невозможно (если только в 16 бит) - то как БЫСТРО (с точки зрения тактов) обращатся с 16-ти битной табличкой? (чтоб умножение было вида 16=8*8 бит)

Titus
21.10.2011, 01:34
Сгенерить на Бейсике или на Си. Пример написать?

Destr
21.10.2011, 01:40
Сгенерить на Бейсике или на Си. Пример написать?
Да, если не трудно.
В С не разбираюсь.
Бейсик (а лучше ZX-бейсик) - самое оно.

---------- Post added at 01:40 ---------- Previous post was at 01:39 ----------

И хорошо-бы пояснения как от этой сгенереной таблички взять тангенс.
Ну в виде:
На входе reg = angle
На выходе reg = TAN(angle)
(p.s. запарился тут с rp)

Titus
21.10.2011, 02:01
Пример программы:
http://s017.radikal.ru/i444/1110/67/082116e0a33b.png

Результат работы:
http://i057.radikal.ru/1110/ef/70467861f3d3.png


Пример программы, генерящей 8-битный тангенс 0..Pi*2, с точностью 1.3.4, где 1 - это бит знака, 3 - это целая часть, 4 - это дробная часть. Или говоря еще проще, это тангенс умноженный на 16. Генерируемая таблица располагается по адресу 0x8000. Горизонтальные линии на графике - это область насыщения функции, где она ограничивается разрядностью 8-битных данных. Если менять множитель в строке 30, то можно смещать формат представления числа. Например, 16, как сейчас - это 4 бита на дробную часть. 32 - это 5 бит, и т.д. Но, чем больше бит на дробную часть, тем большая часть функции попадает в насыщение, но выше точность на остальной части функции.

Titus
21.10.2011, 02:14
Кстати, если вы собираетесь потом на него что-то не только умножать, но и делить, неплохо бы иметь вторую таблицу котангенса, и таким образом привести деление к умножению.

Vitamin
21.10.2011, 07:36
Кстати, если вы собираетесь потом на него что-то не только умножать, но и делить, неплохо бы иметь вторую таблицу котангенса, и таким образом привести деление к умножению.
А если набор чисел, на которые умножается тангенс, невелик, то сразу рассчитать набор таблиц:


;in:
;L=angle
;A=len
;out:
;A=len*tan(angle)
add a,'Table
ld h,a
ld a,(hl)

Andrew771
21.10.2011, 10:12
Ё-моё, да вы чё?
Вспоминаем курс алгебры:

tg x = sin x / cos x

ctg x = 1 / tg x = cos x / sin x

Вот и получаем эти таблички. Можно даже хранить только sin x и cos x, а tg x получать делением при расчетах.

Vitamin
21.10.2011, 10:26
Ё-моё, да вы чё?
Вспоминаем курс алгебры:
Ё-моё, да ты чё?
Вспоминаем, что деление на спектруме- крайне дорогая операция.

Andrew771
21.10.2011, 10:32
ну тогда на бейсике заранее рассчитываем и строим таблицу тангенсов по приведенным формулам.

GM BIT
21.10.2011, 11:09
Вспоминаем, что деление на спектруме- крайне дорогая операция.
Один раз поделить не так уж и дорого
Достаточно иметь одну табличку sin или cos в 256 байт
Взяли числитель сдвинулись на 64 байта взяли знаменатель, поделили, получили тангенс. Проблем на 2р убытка

Vitamin
21.10.2011, 11:23
Один раз поделить не так уж и дорого
А почему один раз? Если нам нужно однократный расчет тангенса, то его проще захардкодить.

Destr
21.10.2011, 11:30
Кстати, если вы собираетесь потом на него что-то не только умножать, но и делить, неплохо бы иметь вторую таблицу котангенса, и таким образом привести деление к умножению.
Да это мысль, спасибо!

---------- Post added at 11:30 ---------- Previous post was at 11:25 ----------

И ещё:
Кто нибудь может разъяснить про "дробный байт"?
Вот например 0.5 это #0080
Если умножить его на любой байт, то получим половину этого байта (в старшем байте).
Всё правильно.
А вот как выглядит в HEX -0.5 ?
Не могу себе представить и не описано нигде.

Vitamin
21.10.2011, 11:57
А вот как выглядит в HEX -0.5 ?
Не могу себе представить и не описано нигде.
0xff80

Destr
21.10.2011, 12:41
0xff80
А я думал что это -1.5
Спасибо, работает!
Получается что младший байт - беззнаковый, а старший - со знаком.

Может у вас есть и хорошая процедура деления?
(вида 8.8=8/8, только не такая как в Sp.Expert и ZX-Format описывается, у них там либо с ограничением, либо наворотов до небес)

Vitamin
21.10.2011, 13:04
Может у вас есть и хорошая процедура деления?
(вида 8.8=8/8, только не такая как в Sp.Expert и ZX-Format описывается, у них там либо с ограничением, либо наворотов до небес)
http://zxdocs.fatal.ru/coding/math.zip

Тебе нужно 16/8. Числитель надо грузить в старший байт, тогда в результате будет 16 битное число с фиксированной точностью.

Titus
21.10.2011, 13:10
А если набор чисел, на которые умножается тангенс, невелик, то сразу рассчитать набор таблиц:
Вот к чему я и говорю, что сначала надо хорошо представлять то, что хочешь рассчитать. А потом уже оптимизировать и делать таблицы.

---------- Post added at 13:10 ---------- Previous post was at 13:10 ----------


ну тогда на бейсике заранее рассчитываем и строим таблицу тангенсов по приведенным формулам.
Да вы, батенька, предыдущую страницу не смотрели)

ZXMAK
21.10.2011, 22:29
http://e-science.ru/img/math/planim/0500501.gif

Barmaley_m
21.10.2011, 23:19
Полностью поддерживаю Titus. Без указания целей использования тангенсов, говорить об их вычислении не имеет смысла. В зависимости от целей можно избрать тот или иной способ вычисления/хранения результата, который в данных конкретных обстоятельствах будет эффективным, а в других обстоятельствах - неточным, медленным или вообще неприменимым.

Более того, я вообще не понимаю, зачем могут понадобиться тангенсы. Обычно, если сталкивался с тригонометрией при графических вычислениях, я имел дело с арктангенсами (т.е. обратной функцией). Прежде, чем быстро или медленно вычислять эти функции, неплохо бы детально разобраться в применяемых формулах, преобразовать их исходя из имеющихся вычислительных возможностей. Может быть, от тангенсов вообще удастся избавиться. Часто бывает, что тангенс угла tg(x) заменяют его аргументом tg x ~= x, и это дает приемлемую точность при небольших значениях x.

Вообще от тангенсов желательно избавляться, если возможно. Эта функция ведет себя плохо с точки зрения программирования - она уходит в бесконечность при конечных значениях аргумента (x=pi/2). В окрестностях агрумента x=pi/2 из-за этого всегда будут неприятности, при любой точности хранения или вычисления тангенсов.

Destr
26.10.2011, 17:44
Замутил вот такую процедуру деления


DIVS; H.L=C/B
LD A,C
XOR B
EXA
LD A,C
NEG
JP M,$+4
LD C,A
LD A,B
NEG
JP M,$+4
LD B,A
XOR A
DUP 8
RL C
RLA
CP B
JR C,$+3
SUB B
CCF
RL H
EDUP
DUP 8
RL C
RLA
CP B
JR C,$+3
SUB B
CCF
RL L
EDUP
EXA
RET P
EX HL,DE
LD HL,0
OR A
SBC HL,DE
RET


Но порой она ошибается.
Где глюк не пойму. Кто знает?

Titus
26.10.2011, 18:09
Но порой она ошибается.
Где глюк не пойму. Кто знает?
Есть несколько замечаний:
Ты делишь 7-битное число на 7-битное, т.к. оба со знаком, но при этом делаешь 16 итераций, словно у тебя не C делится на B, а какая-то регистровая пара типа C1.C2 делится на B. После первых 8 сдвигов в C уже ничего не остается, и второй цикл работает вхолостую. Мало того, если в H у тебя предварительно мусор, то он уже со второй восьмерки итераций окажется в регистре C, и будет фактически деление C.H/B. Вернее даже что-то типа H=C/B, L=H/B.

Destr
26.10.2011, 18:56
Есть несколько замечаний:
Ты делишь 7-битное число на 7-битное, т.к. оба со знаком, но при этом делаешь 16 итераций, словно у тебя не C делится на B, а какая-то регистровая пара типа C1.C2 делится на B. После первых 8 сдвигов в C уже ничего не остается, и второй цикл работает вхолостую. Мало того, если в H у тебя предварительно мусор, то он уже со второй восьмерки итераций окажется в регистре C, и будет фактически деление C.H/B. Вернее даже что-то типа H=C/B, L=H/B.
А как выправить?
Насколько я понял тупо заменить DUP 8 на DUP 7 не получится?

Titus
26.10.2011, 18:58
А как выправить?
Насколько я понял тупо заменить DUP 8 на DUP 7 не получится?
Ты обьясни, что на что и в какой разрядности ты хочешь получить.

Destr
26.10.2011, 19:00
Ты обьясни, что на что и в какой разрядности ты хочешь получить.
Нужно вычислить длину гипотенузы прямоугольного треугольника, зная при этом один из катетов и синус(косинус).
Катет - 8 бит
Синус(косинус) - тоже 8 бит.
Итак, гипотенуза равна катет/синус.

Titus
26.10.2011, 19:04
Нужно вычислить длину гипотенузы прямоугольного треугольника, зная при этом один из катетов и синус(косинус).
Катет - 8 бит
Синус(косинус) - тоже 8 бит.
Итак, гипотенуза равна катет/синус.
Еще раз предлагаю уйти от делений по возможности. Побитное деление всегда более тормозной процесс, чем умножение. А у тебя деление на константу (синус). Так сделай таблицу чисел 1/синус, и применяй умножение.

Destr
26.10.2011, 19:12
Еще раз предлагаю уйти от делений по возможности. Побитное деление всегда более тормозной процесс, чем умножение. А у тебя деление на константу (синус). Так сделай таблицу чисел 1/синус, и применяй умножение.
Синусы для разных углов - разные (и порой 1/sin=хзч, так как синус = 0 бывает)
И вообще это двухбайтное значение получается. Очень смахивает на тангенс по упоротости. Так что тормоза остаются при нас :)
Вот я мучался с этими таблицами, мучался и решил тупо делить по-честному.
Но тоже не получается :(

Titus
26.10.2011, 19:23
Синусы для разных углов - разные (и порой 1/sin=хзч, так как синус = 0 бывает)
В чем проблема? Допустим у тебя таблица на 256 значений синуса, и 256 значений обратного синуса. Две таблички маленьких. Даже если по 16 бит значения. Что же касается деления на ноль, то это плюс бесконечность, т.е. подставляешь туда максимально большое число, и будет тебе щастье. Соотвественно число обратное 1/0 будет именно бесконечностью. Допустим для примера, у тебя самое большое число - это +127, значит 1/0 - это +127.

Destr
26.10.2011, 19:30
В чем проблема? Допустим у тебя таблица на 256 значений синуса, и 256 значений обратного синуса. Две таблички маленьких. Даже если по 16 бит значения.
Да вот табличка обратного синуса в 512 выходит.
А умножать 16*8 бит тоже не особо получается корректно.
Непонятно какой разряд для CP брать.
Это при том, что 8*8 бит умножение работает на ура.
Ломаю голову как-бы 8-ми битную табличку для обратного синуса замутить (заодно и для обратного тангенса, сейчас для него юзаю 32 таблички по 512 байт каждая)

Titus
26.10.2011, 19:34
Да вот табличка обратного синуса в 512 выходит.
А умножать 16*8 бит тоже не особо получается корректно.
Непонятно какой разряд для CP брать.
Это при том, что 8*8 бит умножение работает на ура.
Ломаю голову как-бы 8-ми битную табличку для обратного синуса замутить (заодно и для обратного тангенса, сейчас для него юзаю 32 таблички по 512 байт каждая)
Что такое CP?
Готовые процедуры деления и умножения я видел в каком-то из журналов, да и на форуме не раз проскакивали.

Destr
26.10.2011, 19:50
Что такое CP?
Готовые процедуры деления и умножения я видел в каком-то из журналов, да и на форуме не раз проскакивали.
CP это команда сравнения.
Т.е.
LD A,старший байт от деления
CP старший байт от другого деления
выясняем какая из гипотенуз длинней.

А всякие умножалки-делилки - да я их тоже видел (одну из них выше приводил).
Но они везде со своими ограничениями (либо точность, либо разрядность, либо ещё какая беда)
Нет аналогов писишным mul и div.
Ну по крайней мере только (+-)16=8*8 бит у меня есть (которую "изобрёл" сам, после упорного разбирательства "двоичного умножения в столбик", разумеется "открытие" это только для себя, другие люди уже юзали подобные вещи).
А других провереных (и главное - понятных как работают) процедур нема.

Titus
26.10.2011, 19:57
Еще раз повторюсь, что не понимаю, в чем проблема.
Может попробовать помоделировать весь алгоритм на си, а потом уже переносить на асм, со знанием всего процесса целиком.

Destr
26.10.2011, 20:12
Еще раз повторюсь, что не понимаю, в чем проблема.
Может попробовать помоделировать весь алгоритм на си, а потом уже переносить на асм, со знанием всего процесса целиком.
Ну как объяснить в чём проблема?
Да хрен её знает в чём!
Я подозреваю что процедура деления неправильно работает.
А может быть и ещё что-то у меня не так.
Хотя чего там не так? делим катет на синус, катет известен, синус тоже проверен, по нему нормально всё остальное вертится. А вот длину гипотенузы вычислить не получается (точнее получается, но иногда почему-то, результат неправильный).
Вот я и поинтересовался как выправить процедуру деления которую я привёл.
(ну или как вариант - чем заменить чтоб такая-же разрядность и чтоб знаки)


Может попробовать помоделировать весь алгоритм на си, а потом уже переносить на асм, со знанием всего процесса целиком.

Ну статью Шируотаку, я её выше приводил промоделировать :)
Хотя на С это всё заработает на ура (там ведь умножения/деления правильные готовые, их не надо "изобретать на коленке")

В общем вопрос по-прежнему:
Процедура деления вида (+-)8.8=8/8
Есть?

Titus
26.10.2011, 20:23
В общем вопрос по-прежнему:
Процедура деления вида (+-)8.8=8/8
Есть?
Бери любую 16=16/8, сдвинув предварительно делимое влево на 8 бит)

Destr
26.10.2011, 20:38
Бери любую 16=16/8, сдвинув предварительно делимое влево на 8 бит)
Пробовал.
Может быть не те процедуры?
Дайте пожалуйста провереную (и желательно учитывающую знаки).
Попробую и отчитаюсь что и как получилось.

Titus
26.10.2011, 20:50
Пробовал.
Может быть не те процедуры?
Дайте пожалуйста провереную (и желательно учитывающую знаки).
Попробую и отчитаюсь что и как получилось.
У меня на вскидку нет подобных процедур.

Destr
26.10.2011, 21:05
У меня на вскидку нет подобных процедур.
Вот он, мой камень преткновения :)
Перебрал разные варианты, но они все беззнаковые, а пытаюсь сделать знаковыми - что-то делаю не так видимо и не работает как надо.
И никто ничерта не может помочь кроме как советами.
А мне-бы практику, работающую процедурку...

Хотя надо признать я пробовал вычислять гипотенузу и через сумму квадратов катетов и её корень, но тоже не преуспел (даже на скорость пока что положил).
Там ведь тоже важна дробная часть, а корня с дробью что-то не нашёл.

NovaStorm
26.10.2011, 21:43
Пробовал.
Может быть не те процедуры?

http://baze.au.com/misc/z80bits.html#2.2
Эта?

Destr
26.10.2011, 21:50
http://baze.au.com/misc/z80bits.html#2.2
Эта?
Да, эту тоже пробовал.
В общем-то работает она вроде как и неплохо, но если аргуметы знаковые да ещё и значения во всё поле, то...
Короче не универсальна (для данного момента, где 8 бит и точность 1/256 нужна)

NovaStorm
26.10.2011, 22:08
Да, эту тоже пробовал.

А эти?
http://www.erich-foltyn.eu/Technique/Z80-BinaryDivision.html
и похожая


;Divide 16-bit values (with 8-bit result)
;In: Divide HL by divider D
;Out: L = result, H = rest
;
Div12: ld b,8
Div12_Loop:
and a
sbc hl,de
jp p,Div12_NoAdd
add hl,de
add hl,hl
djnz Div12_Loop
ret
Div12_NoAdd:
scf
adc hl,hl
djnz Div12_Loop
ret

Destr
26.10.2011, 22:13
А эти?
http://www.erich-foltyn.eu/Technique...yDivision.html
и похожая
Таких не видал. Спасибо, попробую.

Barmaley_m
27.10.2011, 03:26
Destr, сдается мне, что твоя проблема не в процедурах деления, а в твоих формулах. А ну-ка выкладывай формулы в студию!

Зачем тебе представление чисел со знаком, если длина катетов и гипотенузы не может быть отрицательной?

Все правильно тебе сказал Titus: пользуйся умножением, а не делением. Если у тебя в таблице хранятся значения cos(x), на которые надо разделить - то храни в таблице обратные им числа 1/cos(x) и умножай на них, а не дели. При этом значение аргумента x в нормальных условиях никогда не должно быть таким, чтобы его косинус был равен нулю. Если у тебя оказывается, что cos(x)=0 - то в программе ошибка на более раннем этапе ее работы. Ты боишься хранить в таблице результат деления на 0, а что ты предлагаешь взамен? Делить на нуль во время работы программы? Ну-ну.

Если косинус угла равен 0 - то угол равен 90 градусам. Представь себе такой треугольник. У него два угла равны 90 градусам! Чему равна его гипотенуза? На этот вопрос нет ответа, так как такой треугольник не может существовать.

Правильно Titus говорит, проверь сначала свою программу на си или хотя бы на бейсике прежде, чем переводить ее на ассемблер. Проблему надо решать по частям. "Разделяй и властвуй". Надо стремиться локализовать ошибку. У тебя сейчас программа не работает, но ты не знаешь, где. Прекрасно, раздели ее на части. Одна часть - алгоитм умножения, вторая часть - что-то другое. Ты не знаешь, какая из частей неправильно работает. Проверяй их по отдельности. Проверяй отдельно формулы, отдельно косинус, отдельно деление и т.д. После проверки по отдельности, если убедился, что все работает - объединяй части, но постепенно. Объединил 2 из четырех частей - проверь, как они работают в паре. Только когда убедился, что пара работает полностью - добавляй в связку новые элементы.

---------- Post added at 01:26 ---------- Previous post was at 01:17 ----------

И еще один момент. Теорема Пифагора работает. Если не работает твоя программа, использующая эту теорему - значит ошибка в программе либо в постановке задачи, но не в теореме. То, что ты не смог запустить свой алгоритм через теорему Пифагора - это сигнал того, что где-то еще есть ошибки. Ищи их.

Ghost
27.10.2011, 09:24
Зачем возится с катетом и гипотенузой если есть ряд Маклорена для тригонометрических функций?

Destr
27.10.2011, 15:32
Destr, сдается мне, что твоя проблема не в процедурах деления, а в твоих формулах. А ну-ка выкладывай формулы в студию!
Я ведь давал ссылку.
Вот ещё раз (с картинками): http://zxdn.narod.ru/coding/ig5ray3d.htm
Формулы все там, пытаюсь реализовать эту статью на практике.


Зачем тебе представление чисел со знаком, если длина катетов и гипотенузы не может быть отрицательной?

Синус может :)


Если косинус угла равен 0 - то угол равен 90 градусам. Представь себе такой треугольник. У него два угла равны 90 градусам! Чему равна его гипотенуза? На этот вопрос нет ответа, так как такой треугольник не может существовать.

Верно, но такая ситуация при определённом POV (см.статью) возможна.
И программе вычисления расстояния (суть гипотенузы) в общем-то пофик с чем она имеет дело, с треугольником или ещё с кем. Она должна вычислить координаты точки (точнее точек D и E (см.картинки в статье)и уже умеет это делать, но пока ошибается в оценке этих расстояний и иногда путает какая из точек ближе).


Теорема Пифагора работает.

Даже не думал ставить под сомнение.


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


Зачем возится с катетом и гипотенузой если есть ряд Маклорена для тригонометрических функций?
Не представляю как с ним обращатся (да ещё и реалтайм).
Высшая математика - не та вещь о которой я могу пренебрежительно заметить "Да это легко!" :)

Andrew771
27.10.2011, 17:48
У корня вычисляется только целая часть, потому и неприменима тут теорема Пифагора. С вычислением целой части корня я может быть ещё бы и смирился, но если ещё и дробную считать - это уже слишком жирно для Спека. Отбросил этот подход.
для корня можно тоже заранее рассчитанную таблицу сделать.


такая ситуация при определённом POV (см.статью) возможна.
для крайних параметров лучше делать принудительную проверку вначале и свой кусок кода.

Destr
27.10.2011, 18:51
для корня можно тоже заранее рассчитанную таблицу сделать.
Не представляю как?
(видел статью про корни http://www.zxpress.ru/article.php?id=1819 там один из способов корнеизвлечения - с табличкой, но я так и не понял как это всё работает)

Titus
27.10.2011, 19:11
Не представляю как?
(видел статью про корни http://www.zxpress.ru/article.php?id=1819 там один из способов корнеизвлечения - с табличкой, но я так и не понял как это всё работает)
Корень вычислить не так трудно. Можно вычислять побитно. Можно по таблице, а аппроксимацией между двумя соседними значениями. Можно и просто по таблице, если точность нужна невысокая. Другое дело, что от корней тоже надо уходить по возможности.

---------- Post added at 19:11 ---------- Previous post was at 19:10 ----------

И еще, любое дробное число с фиксированной точкой - это практически тоже самое, что и целое число, только сдвинутое влево и все.

Barmaley_m
27.10.2011, 21:09
Зачем возится с катетом и гипотенузой если есть ряд Маклорена для тригонометрических функций?
Ряд Маклорена (Тейлора) для тригонометрических функций годится разве что для теоретических выкладок или для студентов на первом курсе в качестве иллюстрации основ численных расчетов. Для практического расчета синусов и других триг. функций есть более эффективные методы, например, разложение в ряд по полиномам Чебышева. Именно этот метод используется спектрумовским бейсиком.

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

Destr
02.11.2011, 16:31
;Divide 16-bit values (with 8-bit result)
;In: Divide HL by divider D
;Out: L = result, H = rest
;
Div12: ld b,8
Div12_Loop:
and a
sbc hl,de
jp p,Div12_NoAdd
add hl,de
add hl,hl
djnz Div12_Loop
ret
Div12_NoAdd:
scf
adc hl,hl
djnz Div12_Loop
ret

Вообще не хочет делить как надо.

Та процедура что в ссылке (похожая) - тоже :(

Andrew771
03.11.2011, 09:41
Вообще не хочет делить как надо.

Та процедура что в ссылке (похожая) - тоже
Почти весь код для Спектрума, который я скачивал из инета, не работает или работает неправильно. Всё время приходилось напильничком дорабатывать. Видимо, в статьях сокращают или пишут авторы-теоретики :)

Для деления, ИМХО, нужно написать алгоритм деления столбиком, как в 3-м классе средней школы. Тут даже проще, т.к. только нули и единицы.

---------- Post added at 09:41 ---------- Previous post was at 09:40 ----------

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

Vitamin
03.11.2011, 12:48
Вот рабочие куски кода из моей графической библиотеки (деление беззнаковое).
Все заявления вида "не работает" сопровождать конкретными примерами (типа- на входе числа, на выходе такое, хотя ожидается другое). А то есть подозрения, что у топикстартера проблемы с матчастью.



DIV ;BC=BC/DE HL=BC mod DE
LD HL,0
LD A,16
SLA C
RL B
DIVL ADC HL,HL
SBC HL,DE
JR NC,$+3
ADD HL,DE
RL C
RL B
DEC A
JR NZ,DIVL
LD A,B
CPL
LD B,A
LD A,C
CPL
LD C,A
RET

DIVI
;C=C/B A=C mod B
XOR A
RL C
DUP 8
ADC A,A
SUB B
JR NC,$+3
ADD A,B
CCF
RL C
EDUP
RET

Destr
03.11.2011, 16:14
Для деления, ИМХО, нужно написать алгоритм деления столбиком, как в 3-м классе средней школы. Тут даже проще, т.к. только нули и единицы.
Попытки реализовать были, но успеха мало (ибо в некоторых случаях алгоритм выдаёт некоректный результат из-за переполнения).


А то есть подозрения, что у топикстартера проблемы с матчастью.
За процедуру - спасибо, попробую, а проблемы с матаном - и не скрывал.
Говорил я уже что неуч и могу лажанутся конкретно.
Но выяснить сможет-ли прога разделить 4 на 2 - сумею :)
Вот как она поведёт себя внутри моего кода - тут уже претензии не к прогам (и их авторам/советчикам) а уже к самому себе. Я ведь только учусь, ни к кому претензий нет.

Andrew771
03.11.2011, 16:35
в некоторых случаях алгоритм выдаёт некоректный результат из-за переполнения
ну значит нужно это учитывать в коде, например перед переполнением перегонять старшие биты в другой регистр сдвигами.

VituZz
03.11.2011, 19:48
Злобин, Григорьев. Программирование арифметических операций в микропроцессорах. - М., 1991.

В этой книге приведено много готовых листингов сложений/вычитаний/умножений/делений для знаковых/беззнаковых разной разрядности операндов. А также рассмотрено множество вспомогательных преобразований. Изложение ведётся для ассемблеров ВМ80, ВМ86 и ВМ87, но от ВМ80 к Z80 перейти, по-моему, не проблема.

И таки табличный способ имеет огромные преимущества в скорости. Но нужно применять его в самом общем виде. Для той же теоремы Пифагора: катет1.катет2=гипотенуза. Если разрядность исходных операндов велика, и объём таблицы сравним с объёмом ОЗУ, то можно (применимо к теореме Пифагора) вспомнить, что достаточно половины её объёма, поскольку сочетание катет1.катет2 даст то же значение, что и катет2.катет1. Если нужно ещё уменьшить таблицу, то можно вспомнить, что если катет1 много меньше катета2, то уменьшение его разрядности вдвое почти не скажется на точности результата. В этом случае нужно лишь прикрутить к алгоритму небольшую логику выбора таблиц, тоже относительно небольших.
Разумеется, конкретика целиком и полностью определяется поставленной задачей в наиболее общей её формулировке, чтобы не получилось: "Как с помощью компьютера правильно повесить картину?" - "Возьмите гвоздь. Забейте его молотком. На гвоздь повесьте картину".

NovaStorm
03.11.2011, 21:58
>>Злобин, Григорьев. Программирование арифметических операций в микропроцессорах. - М., 1991.

Нету там подходящего, я ж первым делом туда =)
Только 16/16 на два листа. Ну и плюс под 580й, да. Но книга конечно знатная.

Destr
09.11.2011, 09:48
Всем спасибо за советы, получилось побороть тангенсы.
Во вложении - результат (который правда ещё допиливать и допиливать).
Но видно что работает :)
Дальше буду боротся с "зубцами" и прочим, тангесов вроде больше не предвидится :)
Тему можно закрывать.

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

DimkaM
09.11.2011, 13:01
Мысли в слух, ни коим образом не касающиеся топикстартера, у него свои цели.

Я в этих вещах не шарю, но думаю можно вообще без тригонометрии в коде обойтись.
Сейчас поворот идёт на 1/32 круга, 1/8 стороны получается. Т.е. написать 8 оптимизированных процедур преобразования и обойтись без таблиц и хитрых умножений-делений. Чую многократный прирост производительности.

Ещё раз повторюсь, геометрию не знаю, тем более не умею её программить. Но хотелось бы почитать комменты моего поста.

Titus
09.11.2011, 13:28
Всем спасибо за советы, получилось побороть тангенсы.
Во вложении - результат (который правда ещё допиливать и допиливать).
Но видно что работает :)
Дальше буду боротся с "зубцами" и прочим, тангесов вроде больше не предвидится :)
Тему можно закрывать.

P.S. Снапшот пофикшен под пентагон, управление курсорными клавишами, при нажатом SPACE - обновляется мини-карта, но при этом конечно тормоза небольшие.
Очень шустренько, в мультиколоре. Молодец)

newart
09.11.2011, 14:00
Очень шустренько, в мультиколоре.
Пока рано судить, текстур то нет.

Destr
09.11.2011, 20:28
Я в этих вещах не шарю, но думаю можно вообще без тригонометрии в коде обойтись.
Сейчас поворот идёт на 1/32 круга, 1/8 стороны получается. Т.е. написать 8 оптимизированных процедур преобразования и обойтись без таблиц и хитрых умножений-делений. Чую многократный прирост производительности
Да мы братья по несчастью :)
Я тоже так-же думал - ошибался.
Все что сейчас крутится - делается с помощью заранее просчитаных таблиц (вобравших в себя все советы в этой теме).
Каждая - по 16384 (#4000).
Т.е. быстрей уже не получается.
Ибо УЖЕ НЕТ НИКАКИХ РАСЧЁТОВ.
Вообще.
Только выборка из табличек.
(потому и довольно шустро получилось)
Такие дела.

newart
09.11.2011, 21:00
потому и довольно шустро получилось
Быстрее чем в известной демке?

Titus
10.11.2011, 00:57
Быстрее чем в известной демке?
От твоего 'в известной демке', или же 'всем эта дема хорошо знакома', меня аж передергивает. Ссылка и название.

Destr
10.11.2011, 01:31
От твоего 'в известной демке', или же 'всем эта дема хорошо знакома', меня аж передергивает. Ссылка и название.
Это Слава имеет в виду Stellar (он мне её как-то показывал).
Вот только так и не научился говорить в личку или по аське вот и путает людей :)

jerri
10.11.2011, 09:09
вы только элон кодеру объясните что так и задумывалось а не то что код тормознутый

Destr
10.11.2011, 09:30
вы только элон кодеру объясните что так и задумывалось а не то что код тормознутый
А ему-то что за печаль?

У вас (гуру-мастеров) прям мания какая-то!
Ни с кем я письками не меряюсь, чхать я хотел быстрей мой код или медленней чем у кого-то там.

Перестаньте, на третий раз уже не смешно, ей богу...

jerri
10.11.2011, 10:36
не у нас, гуру, а просто вопрос : почему то что есть в открытом доступе не используется?

Destr
10.11.2011, 10:43
почему то что есть в открытом доступе не используется?
Это что например?

jerri
10.11.2011, 10:48
Кодер говорит что его движок
тот который под 48 к и в демке засветился

ZXMAK
10.11.2011, 13:45
Да мы братья по несчастью :)
Я тоже так-же думал - ошибался.
Все что сейчас крутится - делается с помощью заранее просчитаных таблиц (вобравших в себя все советы в этой теме).
Каждая - по 16384 (#4000).
Т.е. быстрей уже не получается.
Ибо УЖЕ НЕТ НИКАКИХ РАСЧЁТОВ.
Вообще.
Только выборка из табличек.
(потому и довольно шустро получилось)
Такие дела.

а что у тебя за алгоритм трансформации? ты хранишь матрицы заранее просчитанных кватернионов?

jerri
10.11.2011, 14:44
звучит как "Симпеляция диструбных гентронов"

Вопрос в том как оно будет выглядеть при появлении врагов?

Destr
10.11.2011, 15:04
а что у тебя за алгоритм трансформации? ты хранишь матрицы заранее просчитанных кватернионов?
Ну наверное да. Если я правильно понял.

В общем в одной таблице хранятся все координаты внутри квадрата (32х32) которые получаются при данном угле и локальные расстояния.
А во второй - просчитаные и скорректированные в зависимости от угла и расстояния высоты столбцов.


Вопрос в том как оно будет выглядеть при появлении врагов?
Поживем - увидим ;)

alone
10.11.2011, 18:05
Такие вещи нельзя писать в лоб. Потому и тормозит.
Дема называлась Critical error. http://www.youtube.com/watch?v=MchzKT_oufE
Вот сорец рейкастинга (ускорено по сравнению с демой). Юзайте на здоровье.
Запускать W48.H.

alone
10.11.2011, 20:09
В деме атрибуты не использовались, а тут сделано так: если столбец ниже 8 знакомест, то чистятся и прорисовываются только эти 8 знакомест. Всё, что выше и ниже, заливается атрибутами (если уже не залито). Если же столбец выше 8 знакомест, то эти атрибуты стираются (если уже не стёрты).

ZXMAK
11.11.2011, 13:56
звучит как "Симпеляция диструбных гентронов"

и что вы необычного усмотрели? Матричные преобразования используются в любой 3D деме/игрушке/еtc. Также как кватернионы (http://ru.wikipedia.org/wiki/%D0%9A%D0%B2%D0%B0%D1%82%D0%B5%D1%80%D0%BD%D0%B8%D 0%BE%D0%BD%D1%8B_%D0%B8_%D0%B2%D1%80%D0%B0%D1%89%D 0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%BE%D1%81%D1 %82%D1%80%D0%B0%D0%BD%D1%81%D1%82%D0%B2%D0%B0) используются пожалуй в любом современном 3D шутере для задания направления взгляда персонажа и вращения объектов.
Кватернионы удобны тем что позволяют обойти проблему gimbal lock (http://en.wikipedia.org/wiki/Gimbal_lock) и упрощают расчеты для получения интерполяции вращения.

jerri
11.11.2011, 14:14
Alexander Makeev, Ты то в этом живешь :) а я к этому никаким боком :) не та специализзация

GriV
15.01.2012, 18:50
2Alone> В деме выглядит ну очень круто. Это тру-48к (в ютюбе так значилось) или таки 128к?
И ещё, у меня при запуске W48.H на компиляцию выкидывает в басик с странным сообщнием о глюке. ЧЯДНТ?

alone
15.01.2012, 19:29
Компилировать надо на Pentagon 512K. Работает на чистом 48K! Даже медленная память учтена!

GriV
15.01.2012, 22:13
Это имело под собой отличную от "демо" реализацию? (т.е. игра например)?

alone
16.01.2012, 01:50
Лабиринт с поиском выхода можно сделать хоть сейчас. Только хочется чего-то глобального.

jerri
16.01.2012, 09:05
alone, а можно исходник в более приемлемом виде получить?

GriV
16.01.2012, 10:25
Лабиринт с поиском выхода можно сделать хоть сейчас. Только хочется чего-то глобального.
Есть одна мысль, тем паче концепт 48К легко туда вписывается.
Движок Wolfenstein другой нежели тут?
Ощущение что тут FPS повыше.

alone
16.01.2012, 12:41
alone, а можно исходник в более приемлемом виде получить?
Это в каком? Компилируется, запускается, работает.


Движок Wolfenstein другой нежели тут?
Ощущение что тут FPS повыше.
Дык, всё написано заново с нуля :)