-
ЗдОрово! Теперь 49 байт!
Провереный код:
Код:
sintabgen
ld hl,32737-19
ld bc,19+5461/256
ld de,5461+20
exx
ld hl,sintab+#40
ld d,h
ld e,l
ld c,-20+2
loop
dec c
dec c
ld a,c
exx
add e
jr c,$+3
dec d
ld e,a
ld a,c
sub d
jr nc,$+3
dec b
ld c,a
add hl,bc
ld a,h
exx
ld (hl),a
ld (de),a
inc e
dec l
jr nz,loop
ld (hl),l
loop2
xor a
sbc a,(hl)
ld (de),a
inc l
inc e
jr nz,loop2
-
отлично! :)
осталось добавить несколько наборов коэффициентов для разных максимальных "ширин синуса" (63, 31, 15...)
;)
-
по сути программы, получился типичный бризенхем / постройка окружности через похожесть графиков квадрата чисел и синусоиды, только с некоторой добавочной корректировкой приращений.
упрощая вычисления / делая короче, можно вернуться к графику квадрата чисел...
-
Прикинул, что можно выкинуть четвёртый порядок. Погрешность возрастёт примерно до 0.8, что незначительно. Если сейчас получится, то будет альтернативный, чуть менее точный, но более короткий вариант.
-
Вот что получилось:
Код:
sintabgen2 ;; 45 байт
ld SP,-64 ;!!!
ld de,32731-11
ld bc,11+5639/256
ld hl,5639+64
exx
ld hl,sintab+#40
ld d,h
ld e,l
loop
exx
add hl,sp
ld a,c
sub h
jr nc,$+3
dec b
ld c,a
ex de,hl
add hl,bc
ex de,hl
ld a,d
exx
ld (hl),a
ld (de),a
inc e
dec l
jr nz,loop
ld (hl),l
loop2
xor a
sbc a,(hl)
ld (de),a
inc l
inc e
jr nz,loop2
Не так уж сильно и сократилось. Чую есть ещё потенциал упрощения.
-
Рассчитал минимакс-полином второго порядка для косинуса на интервале от 0 до pi/2. Для удобства преобразовал диапазон аргумента из [0..pi/2] в [0..64], чтобы соответствовать таблице длиной в 256 байт. Также вычислял приближение на дискретном множестве точек (целые значения аргумента). Получившаяся формула:
y = 1.0130681110126272 - 3.1409834002847181e-3*x - 2.0249761634779685e-4*x^2
Диапазон аргумента - от 0 до 63 (при этом 64 соответствует pi/2). Диапазон значений функции - обычный для косинуса (от 0 до 1). Можно умножить все коэффициенты на 127, чтобы получить значения в диапазоне 8-битного целого со знаком.
Максимальная абсолютная погрешность данной формулы - 0.0131. Это хуже, чем достижимая для 8-битного целого (0.0039), поэтому лучше будет использовать многочлен 3-го порядка, хоть его точность приближения и избыточна.
-
Выручил указатель стека и ещё немного ужал.
За счёт замены прибавления 64 на сдвиг #44. И то и другое дают перенос раз в четыре цикла. :)
Максимальные отклонения значений в таблице от теории = 0.89.
Код:
sintabgen2 ;; 43 байта
ld de,32731-11
ld hl,11+5639/256
ld bc,65536-(5639+64)/256
exx
ld hl,sintab+#40
ld d,h
ld e,l
ld c,#44
loop
rlc c
exx
jr nc,$+3
inc c
add hl,bc
ex de,hl
add hl,de
ex de,hl
ld a,d
exx
ld (hl),a
ld (de),a
inc e
dec l
jr nz,loop
ld (hl),l
loop2
xor a
sbc a,(hl)
ld (de),a
inc l
inc e
jr nz,loop2
-
Да, об такой код недолго голову сломать :)
-
наоборот, все просто :)
а то использовать/портить SP - только заради одного стабильного изменения старшего байта на каждые 4 отбавки по 64 - это совсем было не дело :)
-
Красиво.
от jr можно избавиться так:
оригинал:
Код:
rlc c
exx
jr nc,$+3
inc c
очень просится ADC HL,BC... но тут всё хитрО :v2_dizzy_botan:
замена:
Код:
xor a
rlc c
exx
adc a,c
ld c,a