Камрады, нужна простая задачка - получить N*4/3. Есть мысли? я сов7 запутался.
Камрады, нужна простая задачка - получить N*4/3. Есть мысли? я сов7 запутался.
Умножь на константу 341 сдвигами, и возьми старший байт.
выходит, проще лукап построить
Друзья. Помогите оптимизировать процедуру.
есть два числа одно от 0 до 64 второе от 0 до 63
нужно их перемножить и результат разделить на 64 (т.е. простую пропорцию сделать)
Просто много параллельно процедур пишу и время на раздумья тратить нету.
сейчас просто перемножаю процедурой 8бит*8бит=16бить и результат двигаю 4 раза впрао, но понимаю что это глупо и тормознуто.
Сначало 8 раз в одну сторону вращаю, потом 4 раза в другую.
; AC=C*В
XOR A
DUP 8
RR C
JR NC,$+3
ADD B
RRA
EDUP
RR C
rlc c : rlca : rlc c : rlca
быстро на ум пришло взять таблицу 64*64 в 4 килобайта. и один операнд сдвигать 2 раза во второй что бы получить смещение в табличке 16*256
Но предложите что нибудь со сдвигами и сложениями , вычитаниями, максимально быстрое .
DUP 6 и код после EDUP не понадобится
если дробная часть и округление не требуются, то RR C тоже не понадобится
если памяти не жалко, можно сделать 64 функции умножающие на числа от 0 до 63, тогда можно выкинуть команды условного перехода, а ADD B поставить там, где они нужны для данного множителя
Не очень понятна задача.
Для умножения попробовать старый индейский способ - по таблице квадратов.
для деления - использовать lut
a(0-63), b(0-64)
a*b/64=4*a*b/(64*4)=(4*a)*b/256
Все просто, 2 раза "add a" затем просто умножаете на b и берете старший байт.
Ну так это тоже самое получается что и у меня. - "2 раза add a" - это два моих вращения. "просто умножаете на b" - это умножение 8бит на 8бит = 16 бит
Так у меня и сейчас работает. То же самое по скорости.
Я хочу умножение оптимизировать в 6 ротаций, вместо 8 влево и потом 2 вправо. как blackmirror предложил, Просто надо просчитать и попробовать, может сходу замена DUP 8 DUP 6 прокатит
надо что-то такое мутить:
if b=64 then exit ;a=a*64/64
a*b/64 = ( (a+b)^2 - a^2 - b^2 ) / 2 / 64 = (a+b)^2 / 64 - a^2 / 64 - b^2 /64 + rra
need table x^2/64 (x=0..126) или возможно x^2/32 + rra:srl a
...или можь вообще так:
;(a+b)^2 - (a-b)^2 = a^2 + b^2 + 2*a*b - a^2 - b^2 + 2*a*b = 4*a*b
a*b/64 = ( (a+b)^2 - (a-b)^2 ) / 4 / 64 = ( (a+b)^2 / 128 - (a-b)^2 / 128 ) + rra
(используется предрасчитанная табличка x^2 / 128 )
...или вообще
a*b/64 = ( (a+b)^2 - (a-b)^2 ) посчитали в HL (двумя взятиями из таблицы) и старший байт забрали в A (это и есть / 4 / 64)
(используется предрасчитанная табличка x^2)
...и как вариант возможной дальнейшей оптимизации, из таблицы не по 2 байта брать (16битное вычитание), а вначале по младшим байтам решение вынести - повлияют ли они на старшие (перенос), и уж потом из таблицы брать и вычитать старшие, с учетом переноса или его отсутствияКод:; ;mul_ac4: ;hl = (a+c)^2 - (a-c)^2 = a*c*4 ld h,sqr_tbl/256 sub c ld l,a add a,c add a,c ld c,(hl) inc h ld b,(hl) ld l,a ld a,(hl) dec h ld l,(hl) ld h,a sbc hl,bc ;/mul_ac4 ld a,h ;a = a*c*4/256 = a*c/64
[при заполнении 512b sqr_tbl таблицы квадратов не забыть квадраты для отрицательных чисел]Код:;a = a*c/64 = ( (a+c)^2 - (a-c)^2 ) / 256 ld h,sqr_tbl/256 sub c ld l,a ld b,(hl) add a,c add a,c ld c,l ld l,a ld a,(hl) sub b inc h ld a,(hl) ld l,c sbc a,(hl)
- - - Добавлено - - -
взять стандартную процедуру побитного деления и раскрыть-расписать, учитывая, что делитель в данном конкретном случае - это просто два включенных бита / две ветки переходов, с невключенными остальными / пустыми веткамиполучить N*4/3. Есть мысли?
3 = %00000011
Последний раз редактировалось char; 10.10.2018 в 23:13.
Эту тему просматривают: 2 (пользователей: 0 , гостей: 2)